<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Spring Datafication</title>
    <link>https://codefast.tistory.com/</link>
    <description>Daily learning Data Structures, spring framework, Design Patterns, and new technologies. 
What you find here might be a summary of what I learned. 
</description>
    <language>ko</language>
    <pubDate>Tue, 7 Apr 2026 07:06:20 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Spring Datafication</managingEditor>
    <image>
      <title>Spring Datafication</title>
      <url>https://tistory1.daumcdn.net/tistory/4930123/attach/e228a29eaee44b31a36445d368072c92</url>
      <link>https://codefast.tistory.com</link>
    </image>
    <item>
      <title>TESTCONTIANERS</title>
      <link>https://codefast.tistory.com/47</link>
      <description>&lt;h3&gt;The question is how do you match database infrastructure of your test environment with the production one?&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/dbFLow.png?raw=true&quot; alt=&quot;db flow&quot; title=&quot;db flow&quot;&gt;&lt;/p&gt;
&lt;p&gt;Most commonly developers use in-memory databases like &lt;strong&gt;H2 or HSQLDB.&lt;/strong&gt; But what if you want to test your code against &lt;strong&gt;SAME/REAL DATABASE INFRASTRUCTURE IN PRODUCTION?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Amigoscode &lt;a href=&quot;https://www.youtube.com/watch?v=27t5I-9VaPQ&amp;amp;ab_channel=Amigoscode&quot;&gt;stop using H2 in memory-database RIGHT NOW&lt;/a&gt; Provides a better explanation in code but let&amp;#39;s see&lt;br&gt;how we can do it in practice.&lt;/p&gt;
&lt;h3&gt;DOWNSIDES OF IN-MEMORY DATABASES&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Lack of support for some SQL features constrains cause less realistic tests(Reduced reliability)&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/h2-db-downside.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;POSSIBLE SOLUTION TestContainers&lt;/h3&gt;
&lt;p&gt;You can USE &lt;a href=&quot;https://www.testcontainers.org/&quot;&gt;TestContainers&lt;/a&gt; library. It allows you to run a real database in a docker container and connect to it from your tests.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/testContainers.png?raw=true&quot; alt=&quot;testContainers official site&quot; title=&quot;testContainers official site&quot;&gt;&lt;/p&gt;
&lt;h4&gt;How does testContainers work?&lt;/h4&gt;
&lt;p&gt;TestContainers uses DOCKER API. PORT exposes to the host machine.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Starts a container with the DB.&lt;/li&gt;
&lt;li&gt;Exposes the &lt;strong&gt;PORT of DB.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provides and Connect the JDBC URL&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Container is &lt;strong&gt;destroyed after tests are finished&lt;/strong&gt;.  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/howTestContainersWork.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3&gt;HOW TO USE IT ?&lt;/h3&gt;
&lt;p&gt;In a simple maven application we can add the following dependency to our pom.xml file:&lt;br&gt;Based on the database we are using we can add appropriate infrastructure dependency.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;project &amp;gt;
    &amp;lt;!--...--&amp;gt;
  &amp;lt;properties&amp;gt; 
      &amp;lt;testcontainers.version&amp;gt;1.17.6&amp;lt;/testcontainers.version&amp;gt;
  &amp;lt;/properties&amp;gt;
  &amp;lt;dependencies&amp;gt;
      &amp;lt;!--TEST CONTAINERS--&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.testcontainers&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;testcontainers&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.testcontainers&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;junit-jupiter&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;

        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.testcontainers&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;postgresql&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;!--END TEST CONTAINERS--&amp;gt; 
    &amp;lt;/dependencies&amp;gt;
    &amp;lt;dependencyManagement&amp;gt;
        &amp;lt;dependencies&amp;gt;
            &amp;lt;dependency&amp;gt;
                &amp;lt;groupId&amp;gt;org.testcontainers&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;testcontainers-bom&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;${testcontainers.version}&amp;lt;/version&amp;gt;
                &amp;lt;type&amp;gt;pom&amp;lt;/type&amp;gt;
                &amp;lt;scope&amp;gt;import&amp;lt;/scope&amp;gt;
            &amp;lt;/dependency&amp;gt;
        &amp;lt;/dependencies&amp;gt;
    &amp;lt;/dependencyManagement&amp;gt;
&amp;lt;/project&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Lets have a look at how we can test our &lt;strong&gt;DAO layer with testContainers&lt;/strong&gt;.  &lt;/p&gt;
&lt;p&gt;In this instance we would like to test our&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public interface UserEntityRepository extends CrudRepository&amp;lt;UserEntity, String&amp;gt; {
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can start our &lt;strong&gt;TEST&lt;/strong&gt; by first removing &lt;strong&gt;@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE))&lt;/strong&gt;the &lt;strong&gt;default embedded database&lt;/strong&gt; for testing&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
public class UserEntityRepositoryTest {
    @Container
    private static GenericContainer&amp;lt;?&amp;gt; container= new PostgreSQLContainer&amp;lt;PostgreSQLContainer&amp;gt;(&amp;quot;postgres:13&amp;quot;)
            .withExposedPorts(5432)
            .withEnv(&amp;quot;POSTGRES_USER&amp;quot;, &amp;quot;test&amp;quot;)
            .withEnv(&amp;quot;POSTGRES_PASSWORD&amp;quot;, &amp;quot;test&amp;quot;)
            .withEnv(&amp;quot;POSTGRES_DB&amp;quot;, &amp;quot;test&amp;quot;);

    @Test
    public void givenUserName_canSelectByUsername() {

    }

}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The above method is a &lt;strong&gt;generic way of starting&lt;/strong&gt; a container.&lt;br&gt;We can be more specific by using the following method:&lt;br&gt;Also we can tell spring to use dynamic properties for the test.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@Testcontainers
public class UserEntityRepositoryTest {
    @Container
    private static PostgreSQLContainer&amp;lt;?&amp;gt; container= new PostgreSQLContainer&amp;lt;PostgreSQLContainer&amp;gt;(&amp;quot;postgres:13&amp;quot;); 
    @DynamicPropertySource
    static void setUpDB(DynamicPropertyRegistry registry){
        registry.add(&amp;quot;spring.datasource.url&amp;quot;,container::getJdbcUrl );
        registry.add(&amp;quot;spring.datasource.password&amp;quot;, container::getPassword);
        registry.add(&amp;quot;spring.datasource.username&amp;quot;, container::getUsername);
    }

    @Test
    public void givenUserName_canSelectByUsername() {

    }

}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we check the &lt;strong&gt;EXTENDED classes(TestcontainersExtension)&lt;/strong&gt; of the TestContainers we can see that it has a lot of useful methods.&lt;strong&gt;That tracks all the JUNIT life cycle&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/testContainerExtension.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can follow the logs by running our test class again.  &lt;/p&gt;
&lt;p&gt;But then a better log view configuration for the test resource is provided from the official site.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;configuration&amp;gt;
    &amp;lt;appender name=&amp;quot;STDOUT&amp;quot; class=&amp;quot;ch.qos.logback.core.ConsoleAppender&amp;quot;&amp;gt;
        &amp;lt;encoder&amp;gt;
            &amp;lt;pattern&amp;gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n&amp;lt;/pattern&amp;gt;
        &amp;lt;/encoder&amp;gt;
    &amp;lt;/appender&amp;gt;

    &amp;lt;root level=&amp;quot;info&amp;quot;&amp;gt;
        &amp;lt;appender-ref ref=&amp;quot;STDOUT&amp;quot;/&amp;gt;
    &amp;lt;/root&amp;gt;

    &amp;lt;logger name=&amp;quot;org.testcontainers&amp;quot; level=&amp;quot;INFO&amp;quot;/&amp;gt;
    &amp;lt;!-- The following logger can be used for containers logs since 1.18.0 --&amp;gt;
    &amp;lt;logger name=&amp;quot;tc&amp;quot; level=&amp;quot;INFO&amp;quot;/&amp;gt;
    &amp;lt;logger name=&amp;quot;com.github.dockerjava&amp;quot; level=&amp;quot;WARN&amp;quot;/&amp;gt;
    &amp;lt;logger name=&amp;quot;com.github.dockerjava.zerodep.shaded.org.apache.hc.client5.http.wire&amp;quot; level=&amp;quot;OFF&amp;quot;/&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Our test class logs looks like below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/testContainerLogs.png?raw=true&quot; alt=&quot;testContainerLogs&quot; title=&quot;testContainerLogs&quot;&gt;&lt;/p&gt;
&lt;h2&gt;The Test Passed. But then ?&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/testPasses.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The test passes, but then do we need to &lt;strong&gt;create a new container for each test Class?&lt;/strong&gt;  &lt;/p&gt;
&lt;p&gt;Our code&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; @Container
    private static PostgreSQLContainer&amp;lt;?&amp;gt; container= new PostgreSQLContainer&amp;lt;&amp;gt;(&amp;quot;postgres:13&amp;quot;);
    @DynamicPropertySource
    static void setUpDB(DynamicPropertyRegistry registry){
        registry.add(&amp;quot;spring.datasource.url&amp;quot;,container::getJdbcUrl );
        registry.add(&amp;quot;spring.datasource.password&amp;quot;, container::getPassword);
        registry.add(&amp;quot;spring.datasource.username&amp;quot;, container::getUsername);
    }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Would repeat in several classes.&lt;/p&gt;
&lt;h3&gt;POSSIBLE NOT&lt;/h3&gt;
&lt;p&gt;We can create an abstract class that would be extended by all the test classes.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@Testcontainers
public abstract class DBAbstractionTest {
    @Container
    private static PostgreSQLContainer&amp;lt;?&amp;gt; container= new PostgreSQLContainer&amp;lt;&amp;gt;(&amp;quot;postgres:13&amp;quot;);
    @DynamicPropertySource
    static void setUpDB(DynamicPropertyRegistry registry){
        registry.add(&amp;quot;spring.datasource.url&amp;quot;,container::getJdbcUrl );
        registry.add(&amp;quot;spring.datasource.password&amp;quot;, container::getPassword);
        registry.add(&amp;quot;spring.datasource.username&amp;quot;, container::getUsername);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And still our test would pass.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/stillPassesWithAbstraction.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;A Better Approach&lt;/h2&gt;
&lt;p&gt;TestContainers provides a way to &lt;strong&gt;&lt;a href=&quot;https://www.testcontainers.org/modules/databases/jdbc/&quot;&gt;reuse the same container&lt;/a&gt;&lt;/strong&gt; for all the test classes.  &lt;/p&gt;
&lt;p&gt;Which provides a profile for the test classes.  &lt;/p&gt;
&lt;p&gt;And it has specification for each db infrastructure.  &lt;/p&gt;
&lt;p&gt;In our case we are using &lt;strong&gt;PostgreSQLContainer&lt;/strong&gt; at src/test/resources/application-postgres.properties&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;spring.datasource.url=jdbc:tc:postgresql:13:///omayfas
spring.test.database.replace=none&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;By simply adding these properties with our active profile set to &lt;strong&gt;postgres&lt;/strong&gt;&lt;br&gt;We still get a passed test.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ActiveProfiles(&amp;quot;postgres&amp;quot;)
public class UserEntityRepositoryTest {
    @Autowired
    UserEntityRepository userEntityRepository;
    @Test
    @DisplayName(&amp;quot;Given USER EXISTS, when findByName, then return UserEntity&amp;quot;)
    public void givenIfUserExist_canQueryByName() {
        userEntityRepository.save(new UserEntity(&amp;quot;test&amp;quot;, &amp;quot;test&amp;quot;, &amp;quot;test@gmail.com&amp;quot;, &amp;quot;test&amp;quot;, &amp;quot;test.png&amp;quot;, LoginProvider.APP));
        Optional&amp;lt;UserEntity&amp;gt; test = userEntityRepository.findByName(&amp;quot;test&amp;quot;);

        Assertions.assertThat(test).hasValueSatisfying(ue -&amp;gt; {
            Assertions.assertThat(ue.getName()).isEqualTo(&amp;quot;test&amp;quot;);
            Assertions.assertThat(ue.getProvider()).isEqualTo(LoginProvider.APP);
            Assertions.assertThat(ue.getUsername()).isNotNull();
        });

    }

}&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;ERROR WITH PROFILE&lt;/h2&gt;
&lt;p&gt;Notice with no profile we get an error.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/errorWithNoProfileSet.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Because the application test context is not aware of the container.&lt;br&gt;and fails to resolve the datasource properties for the test classes.&lt;br&gt;So our application text context should be like.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@SpringBootTest
@ActiveProfiles(&amp;quot;postgres&amp;quot;)
class OmayfasBlogApplicationTests {

    @Test
    void contextLoads() {
    }

}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;## Conclusion&lt;/p&gt;
&lt;p&gt;Provides a way to test our application with a real database.  &lt;/p&gt;
&lt;p&gt;Ability to test our queries and the database itself.  &lt;/p&gt;
&lt;p&gt;Give it a try.&lt;/p&gt;
&lt;h2&gt;REFERENCES&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/testcontainers&quot;&gt;testcontainers Gitbhub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.testcontainers.org/modules/databases/jdbc/&quot;&gt;testcontainers OFFICIAL SITE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=v3eQCIWLYOw&amp;amp;t=2114s&amp;amp;ab_channel=IntelliJIDEAbyJetBrains&quot;&gt;JetBrains&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=27t5I-9VaPQ&amp;amp;ab_channel=Amigoscode&quot;&gt;AmigosCode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Spring Boot</category>
      <category>Application</category>
      <category>blog</category>
      <category>DAO</category>
      <category>datasource</category>
      <category>postgres</category>
      <category>Profiles</category>
      <category>SpringBootTest</category>
      <category>tectcontainers</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/47</guid>
      <comments>https://codefast.tistory.com/47#entry47comment</comments>
      <pubDate>Thu, 4 May 2023 17:12:19 +0900</pubDate>
    </item>
    <item>
      <title>ALFRESCO CUSTOM MIMETYPES EXTENSION</title>
      <link>https://codefast.tistory.com/46</link>
      <description>&lt;h3&gt;ALFRESCO CUSTOM MIMETYPES EXTENSION&lt;/h3&gt;
&lt;p&gt;In previous &lt;b&gt;alfresco mimetypes extensions custom mimetypes&lt;/b&gt; are defined by adding xml file.&lt;br&gt;In this case, lets consider a &lt;b&gt; custom extension for hwp mimetype&lt;/b&gt;. &lt;/br&gt; at&lt;/p&gt;
&lt;p&gt;&lt;b&gt;alfresco/extension/mimetype/mimetypes-extension-map.xml&lt;/b&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;alfresco-config area=&amp;quot;mimetype-map&amp;quot;&amp;gt;
   &amp;lt;config evaluator=&amp;quot;string-compare&amp;quot; condition=&amp;quot;Mimetype Map&amp;quot;&amp;gt;
      &amp;lt;mimetypes&amp;gt;
         &amp;lt;mimetype mimetype=&amp;quot;application/x-hwp&amp;quot; display=&amp;quot;X-HWP-HWP&amp;quot;&amp;gt;
            &amp;lt;extension&amp;gt;hwp&amp;lt;/extension&amp;gt;
         &amp;lt;/mimetype&amp;gt;
      &amp;lt;/mimetypes&amp;gt;
   &amp;lt;/config&amp;gt;
&amp;lt;/alfresco-config&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This definition copied into the shared directory of the docker instance gives an error of the following type:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;COPY custom-mimetypes-extension-map.xml $TOMCAT_DIR/shared/classes/alfresco/extension/mimetypes/custom-mimetypes-extension-map.xml&lt;/code&gt;&lt;/pre&gt;
&lt;br&gt;


&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;JSON parse error: Unexpected character (&amp;#39;&amp;lt;&amp;#39; (code 60)): expected a valid value (number, String, array, object, &amp;#39;true&amp;#39;, &amp;#39;false&amp;#39; or &amp;#39;null&amp;#39;);
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:2418)
&lt;/code&gt;&lt;/pre&gt;
&lt;br&gt;


&lt;h2&gt;CAUSE OF ERROR&lt;/h2&gt;
&lt;p&gt;This is because the file is &lt;b&gt;not in the correct format.&lt;/b&gt; The file must be in the format JSON. &lt;/br&gt;&lt;/p&gt;
&lt;h2&gt;SOLUTION&lt;/h2&gt;
&lt;p&gt;To solve this problem, we must convert the file into JSON format. &lt;/br&gt;&lt;br&gt;The file &lt;b&gt;custom-mimetypes-extension-map.xml&lt;/b&gt; must be converted to &lt;b&gt;custom-mimetypes-extension-map.json&lt;/b&gt; &lt;/br&gt;&lt;br&gt;Something like this: &lt;br&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
   &amp;quot;mediaTypes&amp;quot;: [
      {
         &amp;quot;name&amp;quot;: &amp;quot;HWP MIME Type&amp;quot;,
         &amp;quot;mediaType&amp;quot;: &amp;quot;application/x-hwp&amp;quot;,
         &amp;quot;extensions&amp;quot;: [
            {&amp;quot;extension&amp;quot;: &amp;quot;hwp&amp;quot;, &amp;quot;default&amp;quot;: true}
         ]
      }
   ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If our &lt;b&gt;custom-mimetypes-extension-map.json&lt;/b&gt; is defined correctly we can verify the &lt;b&gt;newly added mimetype.&lt;/b&gt;&lt;br&gt;From the webscript endpoint &lt;b&gt;http://&lt;server&gt;:&lt;port&gt;/alfresco/service/mimetypes&lt;/b&gt; . &lt;br&gt;&lt;/p&gt;
 &lt;img height=&quot;600px&quot; src=&quot;https://github.com/Fas96/T-images-repo/blob/main/addedMimeType.png?raw=true&quot; width=&quot;100%&quot;/&gt;

 &lt;br&gt;

&lt;p&gt;Also we can verify the property of the newly added mimetype from the &lt;b&gt;alfresco Share UI.&lt;/b&gt; &lt;br&gt;&lt;/p&gt;
&lt;img alt=&quot;share ui mimetype verification&quot; height=&quot;600px&quot; src=&quot;https://github.com/Fas96/T-images-repo/blob/main/verifyProperties.png?raw=true&quot; title=&quot;share ui mimetype verification&quot; width=&quot;100%&quot;/&gt;

&lt;br&gt;</description>
      <category>OPENSOURCE</category>
      <category>Alfresco</category>
      <category>custom-mimetypes-extension</category>
      <category>dockerfile</category>
      <category>evaluator</category>
      <category>JSON</category>
      <category>JSONParser</category>
      <category>mimetype</category>
      <category>MIMETYPES</category>
      <category>UNEXPECTED</category>
      <category>Verification</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/46</guid>
      <comments>https://codefast.tistory.com/46#entry46comment</comments>
      <pubDate>Wed, 19 Apr 2023 22:07:09 +0900</pubDate>
    </item>
    <item>
      <title>ALFRESCO TRANFORMATION ENGINE</title>
      <link>https://codefast.tistory.com/45</link>
      <description>&lt;h2&gt;&lt;strong&gt;ALFRESCO T-ENGINE INTEGRATION 7.3.X&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Alfresco T-Engine has been separated from the legacy Alfresco and now a Standalone application. It uses the features of activeMQ to communicate with Alfresco.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;DOCKER ALL IN ONE TRANSFORMATION CORE ENGINE&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;As alfresco &lt;strong&gt;7.3.X&lt;/strong&gt; is using docker, the default provide transformation core engine is:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-docker&quot;&gt;  transform-core-aio:
    image: alfresco/alfresco-transform-core-aio:3.0.0    mem_limit: 1536m
    environment:
      JAVA_OPTS: &amp;quot; -XX:MinRAMPercentage=50 -XX:MaxRAMPercentage=80&amp;quot;    ports:
      - &amp;quot;8090:8090&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;strong&gt;DOCKER ERROR&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;This image has few errors when it comes to local transformation using the &lt;strong&gt;transform-core-aio(3.0.0) PROVIDED.The MAIN ERROR is that it does not have the correct version of libreoffice installed.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;FROM Personal &lt;strong&gt;trial-and-error&lt;/strong&gt; I realized the &lt;strong&gt;alfresco/alfresco-content-repository-community:7.3.0&lt;/strong&gt;&lt;br&gt; provided core &lt;strong&gt;transform engine&lt;/strong&gt; works best with old images specifically &lt;strong&gt;alfresco/alfresco-transform-core-aio:2.3.6&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-docker&quot;&gt;  transform-core-aio:
    image: alfresco/alfresco-transform-core-aio:2.3.6    mem_limit: 1536m
    environment:
      JAVA_OPTS: &amp;quot; -XX:MinRAMPercentage=50 -XX:MaxRAMPercentage=80&amp;quot;    ports:
      - &amp;quot;8090:8090&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This transformation engine is the one that works best with the &lt;strong&gt;alfresco/alfresco-content-repository-community:7.3.0&lt;/strong&gt; image.. &lt;strong&gt;Notice OTHER VERSIONS OF the transform engine was not TESTED IN THIS PROOF OF CONCEPT&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;NOTICED CHALLENGES&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;As the &lt;strong&gt;transform-core-aio:2.3.6&lt;/strong&gt; is not the latest version of the transformation engine, it has some challenges.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;transform-core-aio:2.3.6&lt;/strong&gt; does not have the &lt;strong&gt;transform-router&lt;/strong&gt; image &lt;strong&gt;RESERVED FOR ENTERPRISE VERSION ONLY&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TIKA:&lt;/strong&gt; LEGACY RECOGNIZED file extensions might be hard to modify.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;&lt;strong&gt;SOLUTIONS&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The &lt;a href=&quot;https://github.com/Alfresco/alfresco-helloworld-transformer&quot;&gt;Alfresco GITHUB Community&lt;/a&gt; provides a solution for implementing Custom local transformations and remote transformationCustom extension for types like hwp can be referenced from the &lt;a href=&quot;https://github.com/Alfresco/alfresco-helloworld-transformer&quot;&gt;Alfresco GITHUB Community&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;REFERENCE&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/aborroy/alf-tengine-ocr&quot;&gt;https://github.com/aborroy/alf-tengine-ocr&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.alfresco.com/transform-service/1.2/config/engine/#develop-a-new-t-engine&quot;&gt;Alfresco Docs - Create custom T-Engine&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://hub.alfresco.com/t5/alfresco-content-services-forum/create-a-transformer-on-share-zip-to-pdf/td-p/241108&quot;&gt;Create a transformer on share ZIP to PDF&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.alfresco.com/content-services/7.0/develop/repo-ext-points/content-transformers-renditions/#creating-a-t-engine&quot;&gt;Alfresco Docs - Content Transformers and Renditions Extension Point&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.alfresco.com/content-services/6.0/admin/transformations/&quot;&gt;Alfresco Docs - Manage transformations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=XV8UzYFFYTI&amp;amp;t=488s&amp;amp;ab_channel=AngelBorroy&quot;&gt;https://www.youtube.com/watch?v=XV8UzYFFYTI&amp;amp;t=488s&amp;amp;ab_channel=AngelBorroy&lt;/a&gt;&lt;/p&gt;</description>
      <category>OPENSOURCE</category>
      <category>docker</category>
      <category>Engine</category>
      <category>error</category>
      <category>extension</category>
      <category>HWP</category>
      <category>imagemagick</category>
      <category>Integration</category>
      <category>tika</category>
      <category>Transform</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/45</guid>
      <comments>https://codefast.tistory.com/45#entry45comment</comments>
      <pubDate>Thu, 13 Apr 2023 09:51:13 +0900</pubDate>
    </item>
    <item>
      <title>SER.1. How to Create Multi-Project Maven POMs</title>
      <link>https://codefast.tistory.com/44</link>
      <description>&lt;h3&gt;Event-driven Spring boot, kafka and elastic&lt;/h3&gt;
&lt;h4&gt;SER.1. How to Create Multi-Project Maven POMs&lt;/h4&gt;
&lt;p&gt;This is a simple example of how to use spring boot, kafka and elastic to create a simple event-driven application.&lt;/p&gt;
&lt;h4&gt;Objectives&lt;/h4&gt;
&lt;p&gt;Our objective is to create a setup POM for our &lt;strong&gt;microservices&lt;/strong&gt;. We will create a parent POM that will be used to manage the versions of the dependencies and plugins used in the microservices.&lt;br&gt;We will also create a POM for each microservice that will inherit from the &lt;strong&gt;parent POM.&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;SER.1.1. Create a parent POM&lt;/h4&gt;
&lt;p&gt;Our &lt;strong&gt;parent POM&lt;/strong&gt; does not contain any code. It is used to manage the &lt;strong&gt;versions of the dependencies&lt;/strong&gt; and plugins used in the microservices.&lt;br&gt;So, It is a POM and not a &lt;strong&gt;war&lt;/strong&gt; or &lt;strong&gt;jar&lt;/strong&gt; package. Which implies we would use it as a base POM for our microservices.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;    &amp;lt;packaging&amp;gt;pom&amp;lt;/packaging&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Our parent POM will inherit from the &lt;strong&gt;spring-boot-starter-parent&lt;/strong&gt; POM. This POM contains the versions of the dependencies and plugins used in the spring boot applications.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; &amp;lt;parent&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-starter-parent&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.0.5&amp;lt;/version&amp;gt;
    &amp;lt;relativePath/&amp;gt; &amp;lt;!-- lookup parent from repository --&amp;gt;
&amp;lt;/parent&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;SER.1.2. Dependency Management&lt;/h4&gt;
&lt;p&gt;This helps define some base &lt;strong&gt;dependencies&lt;/strong&gt; that will be used in the microservices. We can also define the &lt;strong&gt;version&lt;/strong&gt; of the dependencies here.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;dependencyManagement&amp;gt;
        &amp;lt;dependencies&amp;gt;
            &amp;lt;dependency&amp;gt;
                &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;spring-boot-starter&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;${spring-boot.version}&amp;lt;/version&amp;gt;
            &amp;lt;/dependency&amp;gt;

            &amp;lt;dependency&amp;gt;
                &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;spring-boot-starter-test&amp;lt;/artifactId&amp;gt;
                &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
            &amp;lt;/dependency&amp;gt;
        &amp;lt;/dependencies&amp;gt;
    &amp;lt;/dependencyManagement&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;SER.1.3. Build Management&lt;/h4&gt;
&lt;p&gt;Our Build Management contains a section &lt;strong&gt;pluginManagement&lt;/strong&gt;. All the plugins and submodules can use the plugins defined in this section.&lt;br&gt;Without specifying versions.&lt;strong&gt;Additionally, we define a maven compiler plugin&lt;/strong&gt; to use the &lt;strong&gt;java.version&lt;/strong&gt; property defined in the properties section.&lt;br&gt;This is inherited by all the microservices. and the compiler plugin will be set to the value of the &amp;lt;java.version&amp;gt; property.&lt;br&gt;&lt;strong&gt;Note, after java 9, we can use the  release tag to specify the java version.&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;maven-compiler-plugin&amp;lt;/artifactId&amp;gt;
                &amp;lt;version&amp;gt;${maven-compiler-plugin.version}&amp;lt;/version&amp;gt;
                &amp;lt;configuration&amp;gt;
                    &amp;lt;release&amp;gt; ${java.version} &amp;lt;/release&amp;gt;
                &amp;lt;/configuration&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
        &amp;lt;pluginManagement&amp;gt;
            &amp;lt;plugins&amp;gt;
                &amp;lt;plugin&amp;gt;
                    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
                    &amp;lt;artifactId&amp;gt;spring-boot-maven-plugin&amp;lt;/artifactId&amp;gt;
                    &amp;lt;version&amp;gt;${spring-boot.version}&amp;lt;/version&amp;gt;
                &amp;lt;/plugin&amp;gt;
            &amp;lt;/plugins&amp;gt;
        &amp;lt;/pluginManagement&amp;gt;
    &amp;lt;/build&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;SER.1.4. Properties&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Notice&lt;/strong&gt; the notion of &lt;strong&gt;properties&lt;/strong&gt; in the parent POM. We can define properties in the parent POM and use them in the microservices.&lt;br&gt;It is a good practice to define the &lt;strong&gt;versions&lt;/strong&gt; of the dependencies and plugins in the parent POM and use them in the microservices.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;properties&amp;gt;
    &amp;lt;java.version&amp;gt;17&amp;lt;/java.version&amp;gt;
    &amp;lt;spring-boot.version&amp;gt;3.0.5&amp;lt;/spring-boot.version&amp;gt;
    &amp;lt;maven-compiler-plugin.version&amp;gt;3.8.0&amp;lt;/maven-compiler-plugin.version&amp;gt;
&amp;lt;/properties&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;SER.1.5. SUBMODULE CREATION (twitter-to-kafka-service)&lt;/h4&gt;
&lt;p&gt;If we click and select from the context menu, we will see a dialog. We can select the module type and click .&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/1.submodule.png?raw=true&quot; alt=&quot;This module gets data from twitter and puts them in topics of kafka&quot; title=&quot;Submodule twitter-to-kafka-service&quot;&gt;&lt;/p&gt;
&lt;h5&gt;WHAT OUR PARENT POM LOOKS LIKE NOW&lt;/h5&gt;
&lt;p&gt;Our parent module generates a tag to keep &lt;strong&gt;submodules&lt;/strong&gt; inherating from it. We can add the &lt;strong&gt;twitter-to-kafka-service&lt;/strong&gt; module to the tag.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;modules&amp;gt;
        &amp;lt;module&amp;gt;twitter-to-kafka-service&amp;lt;/module&amp;gt;
&amp;lt;/modules&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;SER.1.6. What our twitter-to-kafka-service(Submodule) POM looks like&lt;/h4&gt;
&lt;p&gt;It inherits from the &lt;strong&gt;parent POM&lt;/strong&gt; and contains the &lt;strong&gt;dependencies&lt;/strong&gt; and &lt;strong&gt;plugins&lt;/strong&gt; used in the microservice.&lt;br&gt;Notice the parent of this submodule is our &lt;strong&gt;parent POM&lt;/strong&gt; and not the &lt;strong&gt;spring-boot-starter-parent&lt;/strong&gt; POM.  &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;project
        xmlns=&amp;quot;http://maven.apache.org/POM/4.0.0&amp;quot;
        xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;
        xsi:schemaLocation=&amp;quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&amp;quot;&amp;gt;
    &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;
    &amp;lt;parent&amp;gt;
        &amp;lt;groupId&amp;gt;com.microservices.code&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;microservices-start&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;0.0.1-SNAPSHOT&amp;lt;/version&amp;gt;
    &amp;lt;/parent&amp;gt;
    &amp;lt;artifactId&amp;gt;twitter-to-kafka-service&amp;lt;/artifactId&amp;gt;
    &amp;lt;properties&amp;gt; 
        &amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;
    &amp;lt;/properties&amp;gt;
    &amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-test&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.twitter4j&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;twitter4j-stream&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.projectlombok&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;lombok&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;provided&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt;
    &amp;lt;/dependencies&amp;gt;
    &amp;lt;build&amp;gt;
        &amp;lt;plugins&amp;gt;
            &amp;lt;plugin&amp;gt;
                &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
                &amp;lt;artifactId&amp;gt;spring-boot-maven-plugin&amp;lt;/artifactId&amp;gt;
            &amp;lt;/plugin&amp;gt;
        &amp;lt;/plugins&amp;gt;
    &amp;lt;/build&amp;gt;
&amp;lt;/project&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Summary&lt;/h4&gt;
&lt;p&gt;All subsequent microservices will look like the &lt;strong&gt;twitter-to-kafka-service&lt;/strong&gt; module. The only difference is the &lt;strong&gt;artifactId&lt;/strong&gt; and the &lt;strong&gt;dependencies&lt;/strong&gt; and &lt;strong&gt;plugins&lt;/strong&gt; used in the microservice.&lt;br&gt;&lt;strong&gt;Notice&lt;/strong&gt;  we have not defined the &lt;strong&gt;version&lt;/strong&gt; of the dependencies and plugins. We will use the &lt;strong&gt;version&lt;/strong&gt; defined in the &lt;strong&gt;parent POM&lt;/strong&gt; by default.&lt;br&gt;In the section above, our goal was to see how we can define a parent POM that will be used to manage the versions of the dependencies and plugins used in the microservices.&lt;/p&gt;</description>
      <category>Spring Boot</category>
      <category>maven</category>
      <category>MicroService</category>
      <category>Multi-Project</category>
      <category>parent</category>
      <category>pom</category>
      <category>submodule</category>
      <category>Twitter4J</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/44</guid>
      <comments>https://codefast.tistory.com/44#entry44comment</comments>
      <pubDate>Wed, 5 Apr 2023 22:31:16 +0900</pubDate>
    </item>
    <item>
      <title>How to trigger Mono execution after another Mono terminates</title>
      <link>https://codefast.tistory.com/43</link>
      <description>&lt;h3&gt;Problem&lt;/h3&gt;
&lt;p&gt;I have two Mono&amp;#39;s that I want to execute one after the other. The first Mono returns a value that I want to use in the second Mono. I want to execute the second Mono after the first Mono is done.&lt;br&gt;How can I do this?&lt;/p&gt;
&lt;h4&gt;In this post, we will see how to call a Mono after another Mono is done.&lt;/h4&gt;
&lt;h2&gt;Scenario&lt;/h2&gt;
&lt;p&gt;In an attempt to create some logic, we might require &lt;strong&gt;calling a Mono after another Mono is done&lt;/strong&gt;. In this post, a typical example is with Book Publication Api using &lt;strong&gt;graphql&lt;/strong&gt;.&lt;br&gt;Details of our &lt;strong&gt;pom.xml&lt;/strong&gt; dependencies file might look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;dependencies&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-data-r2dbc&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;io.r2dbc&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;r2dbc-h2&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;com.h2database&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;h2&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;runtime&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt; 
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;io.projectreactor&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;reactor-test&amp;lt;/artifactId&amp;gt;
            &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
        &amp;lt;/dependency&amp;gt; 
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-web&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt; 
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-graphql&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-webflux&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;3.0.4&amp;lt;/version&amp;gt;
        &amp;lt;/dependency&amp;gt;
        &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;spring-boot-starter-data-jpa&amp;lt;/artifactId&amp;gt;
        &amp;lt;/dependency&amp;gt; 
    &amp;lt;/dependencies&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we did have some queries that looks like this: for our db schema, this implies if we want&lt;br&gt;to add a new author, we need to have a book id that already exists in the books table.&lt;/p&gt;
&lt;p&gt;Our SQL SCHEMA FROM START is LIKE THIS:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;create table if not exists books (
  id uuid default random_uuid() not null primary key ,
  bookName varchar(255) not null  ,
  pages int not null
);

CREATE TABLE IF NOT EXISTS  authors(
    id uuid default random_uuid()  not null,
    authorName VARCHAR(255),
    age int not null,
    book_id UUID  NOT NULL,
    CONSTRAINT book_author_fk FOREIGN KEY(book_id) REFERENCES books(id)
)&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Also, imagine our MUTATION SCHEMA looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type Mutation{
    addBook(bookName:String!,pages:Int!,authorName:String,age:Int!):Book
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This implies that anytime we add a book, we can add an author. Our mutation query can send us a payload with all the details required like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;mutation {
  addBook(bookName: &amp;quot;BCJASVM&amp;quot;, pages: 3, authorName:&amp;quot;FasCode&amp;quot;, age: 23) {
    id
    bookName
    pages
    author {
      id
      authorName
      age
    }
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we did send a mutation POST to our service to save this BOOK and AUTHOR with code like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;package com.ease.leaarn.blog.service;

import com.ease.leaarn.blog.model.Author;
import com.ease.leaarn.blog.model.Book;
import com.ease.leaarn.blog.repository.AuthorRepo;
import com.ease.leaarn.blog.repository.BookRepo;
import graphql.schema.DataFetcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

@Service
public class BookService {

    @Autowired
    private BookRepo bookRepo;
    @Autowired
    private AuthorRepo authorRepo;

    @Autowired
    private AuthorService authorService;

    public DataFetcher&amp;lt;CompletableFuture&amp;lt;Book&amp;gt;&amp;gt; getBook() {
        return dataFetchingEnvironment -&amp;gt; {
            String id = dataFetchingEnvironment.getArgument(&amp;quot;id&amp;quot;);
            return bookRepo.getBook(id)
                    .toFuture();
        };
    }

    //getBooks
    public DataFetcher&amp;lt;CompletableFuture&amp;lt;List&amp;lt;Book&amp;gt;&amp;gt;&amp;gt; getBooks() {
       return env-&amp;gt;bookRepo.getBooks().collectList().toFuture();
    }


    //addBook
    public DataFetcher&amp;lt;CompletableFuture&amp;lt;Book&amp;gt;&amp;gt; addBook() {
        return env -&amp;gt; {
            String authorName = env.getArgument(&amp;quot;authorName&amp;quot;);
            String bookName=env.getArgument(&amp;quot;bookName&amp;quot;);
            int pages=env.getArgument(&amp;quot;pages&amp;quot;);
            int age = env.getArgument(&amp;quot;age&amp;quot;); 

            Mono&amp;lt;Book&amp;gt; bookMono = bookRepo.addBook(new Book(bookName, pages));

            authorService.addAuthor(authorName, age, Objects.requireNonNull(bookMono.block()).getId());
            return bookMono.toFuture();
        };
    }

}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Mutations SEEMS TO WORK FINE &lt;strong&gt;BUT IT DOESN&amp;#39;T WORK AS EXPECTED.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/mutations.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can confirm this by checking our database tables. We can see that the author table is empty.&lt;br&gt;Or just send a query to confirm that.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/sendGetAuthorsQueries.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;The Problem&lt;/h3&gt;
&lt;p&gt;What possible could be wrong? Our book saved correctly but the author didn&amp;#39;t.&lt;br&gt;This does not mean our authorService.addAuthor() method is not working.&lt;br&gt;The problem is the ISSUE with &lt;strong&gt;MONO and FUTURE.&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SO, WHAT IS THE ISSUE WITH MONO AND FUTURE?&lt;br&gt;Mono&amp;#39;s are reactive streams. They are non-blocking.&lt;br&gt;They are &lt;strong&gt;asynchronous&lt;/strong&gt;. They are lazy. They are not executed until they are subscribed to.&lt;br&gt;So, this means we can just subscribe our mono to a publisher, and it will be executed.&lt;br&gt;In this example I would simply call the repository method and SUBSCRIBE to it.&lt;br&gt;The changed code would look like this:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;
public DataFetcher&amp;lt;CompletableFuture&amp;lt;Book&amp;gt;&amp;gt; addBook() {
        return env -&amp;gt; {
            String authorName = env.getArgument(&amp;quot;authorName&amp;quot;);
            String bookName=env.getArgument(&amp;quot;bookName&amp;quot;);
            int pages=env.getArgument(&amp;quot;pages&amp;quot;);
            int age = env.getArgument(&amp;quot;age&amp;quot;); 
            Mono&amp;lt;Book&amp;gt; bookMono = bookRepo.addBook(new Book(bookName, pages));
            Mono&amp;lt;Author&amp;gt; authorMono = authorRepo.addAuthor(new Author(authorName, age, Objects.requireNonNull(bookMono.block()).getId()));
            authorMono.subscribe();
            return bookMono.toFuture();
        };
    }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is what the query response looks like now:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/worksWithSubscription.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h3&gt;WAIT A MINUTE, WHAT IS THE ISSUE WITH THIS CODE?&lt;/h3&gt;
&lt;p&gt;We did subscribe and it seems to work. But deep down what just happened?&lt;br&gt;It seems we subscribed to the authorMono, and it executed. But then we forget the only REASON we subscribed to it was to execute it.&lt;br&gt;And also we forget the reason why it did not work in the first place? It was because there was a PREVIOUS bookMono that prevented the authorMono from executing(&lt;strong&gt;DEADLOCK&lt;/strong&gt;).&lt;br&gt;So, it seems to work. and NOW the problem is by default the bookMono in thread is subscribed again. We can confirm that this execute twice in query.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/subscribeTwice.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;SOLUTION:flatMap() can be used to chain the execution of the two mono&amp;#39;s.&lt;br&gt;In our case we can write it like this&lt;br&gt;And it works just fine.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;public DataFetcher&amp;lt;CompletableFuture&amp;lt;Book&amp;gt;&amp;gt; addBook() {
    return env -&amp;gt; { 
        String authorName = env.getArgument(&amp;quot;authorName&amp;quot;); 
        String bookName=env.getArgument(&amp;quot;bookName&amp;quot;); 
        int pages=env.getArgument(&amp;quot;pages&amp;quot;);
        int age = env.getArgument(&amp;quot;age&amp;quot;); 
        Mono&amp;lt;Book&amp;gt; bookMono = bookRepo.addBook(new Book(bookName, pages)) 
        .flatMap(book -&amp;gt; authorRepo.addAuthor(new Author(authorName, age, book.getId())) .map(author -&amp;gt; book) );
        return bookMono.toFuture(); };
}&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;There are possible many other alternatives to solve this problem.&lt;br&gt;I do consider myself a beginner in the world of reactive programming. So definitely there are BETTER and EFFICIENT ways to solve this problem.&lt;/p&gt;
&lt;h3&gt;Reactive Streams Reference&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://r2dbc.io/&quot;&gt;r2dbc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://reflectoring.io/getting-started-with-spring-webflux/&quot;&gt;reflectoring&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.knoldus.com/reactive-java-combining-mono/&quot;&gt;KNOLDUS&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.baeldung.com/java-string-from-mono&quot;&gt;Bauldung&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html&quot;&gt;ProjectReactor&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/50686524/how-to-trigger-mono-execution-after-another-mono-terminates&quot;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/53948698/consume-mono-value-and-use-it-to-call-another-mono&quot;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/51515306/method-call-after-returning-monovoid&quot;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/72697799/call-mono-after-first-mono-is-done-and-return-result-of-first-mono&quot;&gt;stackoverflow&lt;/a&gt;&lt;/p&gt;</description>
      <category>Spring Boot</category>
      <category>GraphQL</category>
      <category>Mono</category>
      <category>mutation</category>
      <category>r2dbc</category>
      <category>reactive</category>
      <category>Streams</category>
      <category>toFuture</category>
      <category>trigger</category>
      <category>WebFlux</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/43</guid>
      <comments>https://codefast.tistory.com/43#entry43comment</comments>
      <pubDate>Thu, 9 Mar 2023 13:14:51 +0900</pubDate>
    </item>
    <item>
      <title>How to Enable root User Login in EC2</title>
      <link>https://codefast.tistory.com/42</link>
      <description>&lt;h3&gt;Cautions&lt;/h3&gt;
&lt;p&gt;For security reasons, you should not use the root user for day-to-day activities. Instead, create an IAM user and use that user to perform administrative tasks.&lt;br&gt;Root user login is disabled by default in Amazon Linux 2 AMI. You can enable root user login by following the steps below.&lt;/p&gt;
&lt;h2&gt;ON EC2 INSTANCE-AMI LINUX 2&lt;/h2&gt;
&lt;p&gt;If we have an EC2 instance with Amazon Linux 2 AMI, we can enable root user login by following the steps below.&lt;br&gt;**&lt;br&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/ROOTUSERLOGINEC2.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;br&gt;**&lt;br&gt;Commonly, the ec2-user is the default user in Amazon Linux 2 AMI. We can check this by running the following command.****&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ whoami&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and also we can verify details of our instance OS by running the following command.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ cat /etc/os-release&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/EC2INSTANCE_CHECK.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The ec2-user might have fewer privileges than the root user. So, we need to enable root user login to perform administrative tasks.  &lt;/p&gt;
&lt;p&gt;It might be more reasonable to create an IAM user and use that user to perform administrative tasks by giving the user enough privileges.  &lt;/p&gt;
&lt;p&gt;The goal of this article is to enable root user login in Amazon Linux 2 AMI.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Enable root user login in Amazon Linux 2 AMI&lt;/h3&gt;
&lt;p&gt;The ec2-user cannot do this changes by default. So, we need to switch to the root user to perform this task.&lt;br&gt;Which implies we need to login as root user in the web-browser console from aws.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Connect&lt;/strong&gt; from the instance details page.&lt;/li&gt;
&lt;li&gt;Change the username to &lt;strong&gt;root&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/switchTOROOT.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;3. From the console, we want to edit the sshd_config file to enable root user login.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/sshd_config.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;We uncomment the &lt;strong&gt;PermitRootLogin yes&lt;/strong&gt;. Save the file and exit(:wq!).&lt;/li&gt;
&lt;li&gt;We want to edit the authorized_keys file .&lt;br&gt;In this file we want to clear all text before the &lt;strong&gt;ssh-rsa&lt;/strong&gt;. Save the file and exit(:wq!).&lt;/li&gt;
&lt;li&gt;We would want to exit the try login as root user.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/ROOTsuccesfulLogin.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;We have enabled root user login in Amazon Linux 2 AMI. We can login as root user from any ssh client.&lt;br&gt;This is not recommended for security reasons. Instead, we should create an IAM user and use that user to perform administrative tasks.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;References&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.netiq.com/documentation/platespin-migrate-12-3/migrate-user/data/aws2x-root-credentials.html&quot;&gt;MICROFOCUS&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://superuser.com/questions/1282740/aws-how-to-switch-as-root-user&quot;&gt;StackExchange&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://superuser.com/questions/931698/logging-into-an-aws-instance-with-a-non-root-user&quot;&gt;StackExchange&lt;/a&gt;&lt;/p&gt;</description>
      <category>DevOps</category>
      <category>administrative</category>
      <category>EC2</category>
      <category>Linux</category>
      <category>OS</category>
      <category>PermitRootLogin</category>
      <category>su</category>
      <category>WhoamI</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/42</guid>
      <comments>https://codefast.tistory.com/42#entry42comment</comments>
      <pubDate>Thu, 2 Mar 2023 22:03:24 +0900</pubDate>
    </item>
    <item>
      <title>ERROR M1 or M2 PLATFORM linux/arm64/v8 Not supported</title>
      <link>https://codefast.tistory.com/41</link>
      <description>&lt;h2&gt;IN MY CASE &lt;code&gt;ERROR IN Alfresco 7.3 IN M1 or M2 PLATFORM linux/arm64/v8 Not supported&lt;/code&gt;&lt;/h2&gt;
&lt;br&gt;

&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&amp;quot;I will love the light for it shows me the way, yet I will endure the darkness because it shows me the stars.&amp;quot; —Og Mandino&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br&gt;
&lt;h4&gt;M2 PLATFORM&lt;/h4&gt; &lt;br&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/PLATFORMFAILS.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;For the pass two weeks, I have been despondent,for the nebulous reason why M1  docker runs an application Successfully.But currently an M2&lt;br&gt;docker fails to run it. I have been trying to figure out why, and I have been unsuccessful until today.&lt;br&gt;&lt;/p&gt;
&lt;br&gt;
**M1 PLATFORM**&lt;br&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/M1_PLATFORM.jpeg?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;Some Docker images does not support some os architectures. Classical example is&lt;br&gt;alfresco which does not support linux/arm64/v8 architectures. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/alfrescoDockerHubSearch.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;But in recent docker release notes, they have added support for running docker images on M1 platform. &lt;br&gt;&lt;br&gt;With rosetta 2, docker can run linux/amd64 images on M1/M2 OS. &lt;br&gt;&lt;br&gt;This feature can be enabled  checking the box in the Docker Desktop preferences. &lt;br&gt;&lt;br&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/enableM2.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3&gt;WELL IS THIS ENOUGH TO RUN ALFRESCO ON M2 PLATFORM? &lt;br&gt;&lt;/h3&gt;
&lt;br&gt;

&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/FAILSV8.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;No, it is not enough. &lt;br&gt;In my case, I have tried to run alfresco on M2 platform, but it fails. &lt;br&gt;&lt;br&gt;There has been several &lt;a href=&quot;https://stackoverflow.com/questions/69054921/docker-on-mac-m1-gives-the-requested-images-platform-linux-amd64-does-not-m&quot;&gt;references&lt;/a&gt; to this issue on the internet, but no solution has been found. &lt;br&gt;&lt;br&gt;&lt;a href=&quot;https://github.com/docker/for-mac/issues/6356&quot;&gt;This&lt;/a&gt; is the issue on docker github. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;br&gt; WONDERING WHY ALFRESCO DOES NOT SUPPORT M2 PLATFORM? &lt;br&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DO I NEED TO INSTALL &lt;a href=&quot;https://docs.docker.com/desktop/install/mac-install/&quot;&gt;ROSETTA &lt;/a&gt;2? &lt;br&gt;&lt;/li&gt;
&lt;li&gt;DO I NEED TO INSTALL &lt;a href=&quot;https://www.qemu.org/&quot;&gt;QEMU&lt;/a&gt; ? &lt;br&gt;&lt;/li&gt;
&lt;li&gt;DO I NEED TO INSTALL &lt;a href=&quot;https://docs.docker.com/build/install-buildx/&quot;&gt;Docker BUILDX&lt;/a&gt; ? &lt;br&gt;&lt;/li&gt;
&lt;li&gt;WOULD CHANGING DEFAULT &lt;a href=&quot;https://docs.docker.com/compose/environment-variables/envvars/&quot;&gt;ENVIRONMENT VARIABLES HELP &lt;/a&gt; ? &lt;br&gt;&lt;br&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;SOLUTIONS TO THE PROBLEM &lt;br&gt;&lt;/h3&gt;
&lt;p&gt;I did try some solutions above, but they did not work. &lt;br&gt; Which I recommend anyone to try too. &lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;p&gt;In the  light of all things, I have decided to master my fear of the unknown. &lt;br&gt;&lt;br&gt;So I &lt;a href=&quot;https://stackoverflow.com/questions/44346109/how-to-easily-install-and-uninstall-docker-on-macos&quot;&gt;deleted&lt;/a&gt; my docker completely and reinstalled it. &lt;br&gt; Checked the box again for the support on apple chips, and restarted.&lt;/p&gt;
&lt;p&gt;Logs from the installation of docker on M2 platform shows its running successfully. &lt;br&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/dockerRunningSuccessfully.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;br&gt;

&lt;h3&gt;SUMMARY &lt;br&gt;&lt;/h3&gt;
&lt;p&gt;I have not been able to work around it any possible way. Definitely uninstalling docker was not the best idea, But in the mirage all that a common man see&amp;#39;s is water.&lt;br&gt;It has been a long journey, but I have finally been able to run image that does not support M2 linux/arm64/v8 architecture. &lt;br&gt;&lt;br&gt;Lessons Do not uninstall like i did try other possible ways if it does not work,go with the norm&lt;br&gt;&lt;/p&gt;</description>
      <category>architectures</category>
      <category>docker</category>
      <category>linux/arm64/v8</category>
      <category>Platform</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/41</guid>
      <comments>https://codefast.tistory.com/41#entry41comment</comments>
      <pubDate>Thu, 2 Mar 2023 12:40:35 +0900</pubDate>
    </item>
    <item>
      <title>COMMON OS RELATED INTERVIEW QUESTIONS</title>
      <link>https://codefast.tistory.com/40</link>
      <description>&lt;p&gt;&lt;i&gt;In most common software interviews, you might come across few of the common related &lt;strong&gt;Operating System(OS)&lt;/strong&gt; questions. Here is the list of some common questions that you might come across in your interview.&lt;br&gt;This list is curated from &lt;a href=&quot;https://leetcode.com/discuss/interview-question/operating-system/3216693/INTRESTING-INTERVIEW-QUESTIONS-IN-OS&quot;&gt;leetcode&lt;/a&gt; and few other sources.&lt;br&gt;As you know, &lt;strong&gt;Operating system&lt;/strong&gt; is a vast topic and it is not possible to cover all the questions in one post. So, I will keep adding more questions to this list as I come across them.&lt;br&gt;Personally, I have not come across any of these questions in my interviews. But, I have seen these questions in other people&amp;#39;s interviews. So, I thought of sharing this list will help people preparing for interviews&lt;br&gt;like myself.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NOTE: &lt;/strong&gt; This post is study &lt;strong&gt;summary &amp;amp; paraphrase&lt;/strong&gt; on various topic, that I have come across in my journey of learning. &lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;1.what is a kernel?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The operating system&amp;#39;s kernel is an essential component which controls &lt;strong&gt;hardware and software functions&lt;/strong&gt;. &lt;/br&gt;&lt;br&gt;In essence, it controls how memory and CPU time are used. &lt;br&gt;It is an essential part of the operating system.&lt;br&gt;The kernel &lt;strong&gt;serves as a link&lt;/strong&gt; between &lt;strong&gt;software programs and hardware-level data processing&lt;/strong&gt; carried out through &lt;strong&gt;system calls and inter-process communication&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When an &lt;strong&gt;operating system is loaded&lt;/strong&gt;, the kernel loads first and &lt;em&gt;stays in memory until the operating system is shut down&lt;/em&gt; once again.&lt;br&gt;&lt;br&gt;It is in charge of several things, including &lt;strong&gt;memory management&lt;/strong&gt;, &lt;strong&gt;task management&lt;/strong&gt;, and &lt;strong&gt;disk management&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The process table in the kernel maintains track of all running processes.&lt;br&gt;• The region table for each process in the process table has an entry that refers to a region table entry.&lt;br&gt;• The region table entry has a pointer to the page table for the region.&lt;br&gt;&lt;br&gt;&lt;br&gt;It chooses which processes should be &lt;strong&gt;retained in main memory for execution and which ones should be assigned to the processor for execution&lt;/strong&gt;. &lt;br&gt;&lt;br&gt;In essence, it serves as a &lt;strong&gt;conduit between hardware and user programs&lt;/strong&gt;. The primary function of the kernel is to control communication between &lt;strong&gt;user-level applications and hardware components like the CPU and disk memory.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt; &lt;strong&gt;Goals of the Kernel:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create communication between hardware and user-level applications.&lt;/li&gt;
&lt;li&gt;Determining the condition of incoming processes&lt;/li&gt;
&lt;li&gt;Handle disk operations.&lt;/li&gt;
&lt;li&gt;Manage memory.&lt;/li&gt;
&lt;li&gt;Manage job completion.&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;&lt;strong&gt;Types of Kernel :&lt;/strong&gt;&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Monolithic Kernel&lt;/strong&gt; : A monolithic kernel is a &lt;b&gt;single &amp;amp; large kernel&lt;/b&gt; where  all operating system services operate in kernel space.&lt;br&gt; It has dependencies between systems components.&lt;br&gt; eg:&lt;b&gt; Unix, Linux, Open VMS, XTS-400 etc.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Micro Kernel&lt;/strong&gt; : The &lt;b&gt; minimalist approach &lt;/b&gt;is used by kernel types. It has &lt;b&gt;thread scheduling and virtual memory&lt;/b&gt;. With fewer services in the kernel area, it is more reliable.&lt;b&gt; Rest is provided in user space.&lt;/b&gt;&lt;b&gt; eg: Mach, L4, AmigaOS,Minix,K42, Exokernel etc.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hybrid Kernel&lt;/strong&gt; : A combination of both monolithic and micro kernels. It has &lt;b&gt;speed and design&lt;/b&gt; of monolithic kernel &lt;b&gt; &amp;amp; &lt;/b&gt; &lt;b&gt; modularity and stability of microkernel&lt;/b&gt;.&lt;b&gt; eg: Windows NT,Netware,BeOS,Plan9 etc.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exo Kernel&lt;/strong&gt; : It is a &lt;b&gt;new type of kernel&lt;/b&gt; which is &lt;b&gt;not monolithic or micro&lt;/b&gt;. It is &lt;b&gt;modular&lt;/b&gt; and &lt;b&gt;has a small core(fewest hardware abstractions as possible)&lt;/b&gt;It follows end-to-end principle and also &lt;b&gt;allocates physical resources to applications&lt;/b&gt;.&lt;b&gt; eg: Nemesis, ExOS etc.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nano Kernel&lt;/strong&gt; : This particular kernel&lt;b&gt; lacks system services but provides hardware abstraction&lt;/b&gt;. The Mini Kernel and Nano Kernel have become comparable since the Micro Kernel likewise lacks system services.&lt;b&gt; eg: EROS etc.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;


&lt;h3&gt;&lt;strong&gt;2.what is a bootstrap program?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;Bootstrapping&lt;/b&gt; is the process of loading a set of instructions when a computer is  &lt;b&gt; first turned on or booted.&lt;/b&gt; &lt;br&gt;&lt;br&gt;&lt;strong&gt;Diagnostic tests are run at startup&lt;/strong&gt;, such as the &lt;strong&gt;power-on self-test (POST)&lt;/strong&gt;, to configure or check device settings and to carry out routine testing for &lt;strong&gt;peripheral, hardware, and external memory device connections.&lt;/strong&gt; The System is then initialized by loading the &lt;strong&gt;bootloader or bootstrap software.&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;
&lt;h5&gt;&lt;strong&gt;Programs that load the OS :&lt;/strong&gt;&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;GNU Grand Unified Bootloader(GRUB):&lt;/strong&gt; It is a &lt;b&gt;multiboot boot loader&lt;/b&gt; that supports &lt;b&gt;multiple operating systems&lt;/b&gt;. It is &lt;b&gt;open source&lt;/b&gt; and &lt;b&gt;free software&lt;/b&gt;. Which implies &lt;b&gt; A multiboot specification that allows the user to choose one of several OSs&lt;/b&gt;.&lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NT Loader(NTLDR):&lt;/strong&gt; It is a &lt;b&gt;bootloader&lt;/b&gt;  for &lt;b&gt;Microsoft’s Windows NT OS that usually runs from the hard drive&lt;/b&gt;. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Linux Loader (LILO):&lt;/strong&gt; It is a &lt;b&gt;bootloader&lt;/b&gt; for &lt;b&gt;Linux&lt;/b&gt; that usually runs from the &lt;b&gt;hard drive&lt;/b&gt; or floppy disc&lt;br&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network Interface Controller (NIC):&lt;/strong&gt; Uses a bootloader that supports booting from a network interface such as Etherboot or pre-boot execution environment(PXE).&lt;br&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;A computer is said to start with a blank main memory before booting. The boot-strap enables a series of applications to load in order to launch the OS. The operating system (OS) is the main program that controls all other programs that are running on a computer. It carries out functions like managing directories and files, controlling peripheral devices like a disc drive, sending output signals to a monitor, and recognizing input signals from a keyboard.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;br&gt;

&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;Bootstrap may also refer to the process of gradually transforming simpler programming environments into more complicated and user-friendly ones. An assembly program plus a basic text editor, for instance, may have been the programming environment in the past. The advanced object-oriented programming languages and graphical integrated development environments of today are the result of decades of incremental advancements (IDEs).&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;

&lt;h3&gt;&lt;strong&gt;3.what is the difference between the kernel and operating system?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;Operating System (OS)&lt;/b&gt; is a system program that &lt;strong&gt;enables communication between a user and a computer&lt;/strong&gt;. When a computer is turned on, &lt;strong&gt;Operating System is the first program to load&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;&lt;strong&gt;The kernel &lt;/strong&gt;is the &lt;b&gt;main element of an Operating System&lt;/b&gt; and is also a system program. It is the part of the &lt;b&gt;Operating System that interprets user commands into machine language.&lt;/b&gt;&lt;br&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Operating System&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Kernel&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;OS is a system software&lt;/td&gt;
&lt;td&gt;Kernel is a system software which is part of the OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OS provides interface between the user and hardware.&lt;/td&gt;
&lt;td&gt;Kernel provides an interface between application and hardware.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;It also provides protection and security&lt;/td&gt;
&lt;td&gt;Main purpose is memory management,disk management,process management and task management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;All system needs operating system to run&lt;/td&gt;
&lt;td&gt;All operating systems need kernel to run&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Types of operating system includes single and multiuser OS, multiprocessor OS,Realtime OS, Distributed OS.&lt;/td&gt;
&lt;td&gt;Type of kernel includes Monolithic and Micro kernel.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First program to load when the computer boots up.&lt;/td&gt;
&lt;td&gt;First program to load when operating system loads.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br&gt;
&lt;hr&gt;

&lt;h3&gt;&lt;strong&gt;4.can a system run without OS?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;b&gt;YES. &lt;/b&gt;&lt;br&gt;&lt;br&gt;Although it seems impossible that a computer would not &lt;strong&gt;exist without an operating system&lt;/strong&gt;, the truth is that &lt;strong&gt;early computers did not exist&lt;/strong&gt;. They were just big machines tasked with one program at a time. In contrast, modern computers have to perform many different tasks, often simultaneously, &lt;strong&gt;so without an operating system a laptop wouldn&amp;#39;t really work.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;5.what sockets do hackers use?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Hackers employ particular sockets or ports.&lt;/strong&gt; Hackers may utilize any open ports or sockets in addition to a variety of tools and techniques to &lt;strong&gt;gain unauthorized access to a system or network.&lt;/strong&gt; It&amp;#39;s important to note that some ports and sockets, &lt;strong&gt;like port 80 for HTTP traffic, port 443 for HTTPS traffic, and port 22 for SSH traffic,&lt;/strong&gt; are more frequently targeted by hackers. &lt;br&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;6.what is a mutex lock?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;A &lt;strong&gt;mutex lock(mutual exclusion)&lt;/strong&gt; is a &lt;strong&gt;synchronization mechanism&lt;/strong&gt; that allows &lt;strong&gt;only one thread&lt;/strong&gt; to access a &lt;strong&gt;critical section&lt;/strong&gt; of code at a time. &lt;br&gt;&lt;br&gt;&lt;strong&gt;Critical section&lt;/strong&gt; is a &lt;strong&gt;portion of code&lt;/strong&gt; that &lt;strong&gt;accesses shared resources&lt;/strong&gt;. &lt;br&gt;&lt;br&gt;In a &lt;strong&gt;multi-threaded environment&lt;/strong&gt;, &lt;strong&gt;multiple threads&lt;/strong&gt; can &lt;strong&gt;access the same critical section&lt;/strong&gt; at the same time. &lt;br&gt;&lt;br&gt;&lt;strong&gt;Mutex lock&lt;/strong&gt; is a &lt;strong&gt;mechanism&lt;/strong&gt; that &lt;strong&gt;prevents multiple threads&lt;/strong&gt; from &lt;strong&gt;accessing the same critical section&lt;/strong&gt; at the same time. &lt;br&gt;&lt;br&gt;Example: &lt;br&gt; database access, file access,input-output devices,network connections etc. &lt;br&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A simple code example of unexpected behavior when a mutex lock is not used in java referenced from baeldung.com can be seen below:&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class SequenceGenerator {

 private int currentValue = 0;

 public  int getNextSequence() {
     currentValue = currentValue + 1;
     return currentValue;
 }

&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt; Set&amp;lt;Integer&amp;gt; getUniqueSequences(SequenceGenerator generator, int count) throws Exception {
    ExecutorService executor = Executors.newFixedThreadPool(3);
    Set&amp;lt;Integer&amp;gt; uniqueSequences = new LinkedHashSet&amp;lt;&amp;gt;();
    List&amp;lt;Future&amp;lt;Integer&amp;gt;&amp;gt; futures = new ArrayList&amp;lt;&amp;gt;();

    for (int i = 0; i &amp;lt; count; i++) {
        futures.add(executor.submit(generator::getNextSequence));
    }

    for (Future&amp;lt;Integer&amp;gt; future : futures) {
        uniqueSequences.add(future.get());
    }

    executor.awaitTermination(1, TimeUnit.SECONDS);
    executor.shutdown();

    return uniqueSequences;
}

@Test
public void givenUnsafeSequenceGenerator_whenRaceCondition_thenUnexpectedBehavior() throws Exception {
    int count = 1000;
    Set&amp;lt;Integer&amp;gt; uniqueSequences = getUniqueSequences(new SequenceGenerator(), count);
    assertEquals(count, uniqueSequences.size());
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
&amp;lt;br&amp;gt;

2. **Expected Generation of Sequence with Mutex Lock Using Synchronization Method Level** &amp;lt;br&amp;gt;
The underlying concept of synchronization is that **only one thread can execute a synchronized method for a given object at a time**. &amp;lt;br&amp;gt;
```java
public class SequenceGeneratorUsingSynchronizedMethod extends SequenceGenerator {

    @Override
    public synchronized int getNextSequence() {
        return super.getNextSequence();
    }

    @Test
    public void givenUnsafeSequenceGenerator_whenSequenceGeneratorUsingSynchronizedMethod_thenExpectedBehavior() throws Exception {
        int count = 1000;
        Set&amp;lt;Integer&amp;gt; uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSynchronizedMethod(), count);
        assertEquals(count, uniqueSequences.size());
    }

}&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;

&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expected Generation of Sequence with Mutex Lock Using Synchronization Block Level&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class SequenceGeneratorUsingSynchronizedBlock extends SequenceGenerator {

 private Object mutex = new Object();

 @Override
 public int getNextSequence() {
     synchronized (mutex) {
         return super.getNextSequence();
     }
 }

 @Test
 public void givenUnsafeSequenceGenerator_whenSequenceGeneratorUsingSynchronizedBlock_thenExpectedBehavior() throws Exception {
     int count = 1000;
     Set&amp;lt;Integer&amp;gt; uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingSynchronizedBlock(), count);
     assertEquals(count, uniqueSequences.size());
 }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;br&gt;

&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expected Generation of Sequence with Mutex Lock Using ReentrantLock&lt;/strong&gt; &lt;br&gt;&lt;br&gt;A closer look at the &lt;strong&gt;ReentrantLock&lt;/strong&gt; class reveals that it is a &lt;strong&gt;synchronization mechanism&lt;/strong&gt; that &lt;strong&gt;implements the Lock interface&lt;/strong&gt;. &lt;br&gt;&lt;br&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/reentrantlock.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;br&gt;
```java
public class SequenceGeneratorUsingReentrantLock extends SequenceGenerator {

&lt;p&gt; private ReentrantLock mutex = new ReentrantLock();&lt;/p&gt;
&lt;p&gt; @Override&lt;br&gt; public int getNextSequence() {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; try {
     mutex.lock();
     return super.getNextSequence();
 } finally {
     mutex.unlock();
 }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; }&lt;/p&gt;
&lt;p&gt; @Test&lt;br&gt; public void givenUnsafeSequenceGenerator_whenRaceCondition_thenExpectedBehavior() throws Exception {&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; int count = 1000;
 Set&amp;lt;Integer&amp;gt; uniqueSequences = getUniqueSequences(new SequenceGeneratorUsingReentrantLock(), count);
 assertEquals(count, uniqueSequences.size());&lt;/code&gt;&lt;/pre&gt;&lt;p&gt; }&lt;br&gt;}&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;br&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Working of a mutex&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1. Supposed one thread has locked a region of code using the mutex and is executing that piece of code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Now if scheduler decides to do a context switch, then all the other threads which are ready to execute the same region are unblocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.Only one of all the threads would make it to the execution but if this thread tries to execute the same region of the code&lt;br/&gt;that is already locked then it would again go to sleep.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. Context switch will take place again and again but no thread would be able to execute&lt;br/&gt;the locked region of the code until the mutex lock over it is released.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5. Mutex lock will only be released by the thread who locked it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6. So this ensures that once a thread has locked a piece of code then no other thread can execute the same region until it is unlocked by the thread who locked it.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;br&gt;
&lt;hr&gt;

&lt;hr&gt;

&lt;h3&gt;&lt;strong&gt;7.what are the types of semaphores?&lt;/strong&gt; &lt;br&gt;&lt;/h3&gt;
&lt;p&gt;There are main two types of semaphores:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Binary Semaphore:&lt;/strong&gt; A binary semaphore is a semaphore with a value of 0 or 1. It is used to control access to a shared resource. It is used to implement mutual exclusion. It is also used to implement synchronization between two processes. It is also used to implement synchronization between two threads.&lt;br&gt;&lt;br&gt;There’s a common misconception that they can be used interchangeably. But in fact, &lt;strong&gt;a semaphore is a signaling mechanism where on the other hand, a mutex is a locking mechanism. So, we need to know that binary semaphore is not a mutex.&lt;/strong&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Counting Semaphore:&lt;/strong&gt; A counting semaphore is a semaphore with a value of 0 or more. It is used to control access to a shared resource. It is used to implement mutual exclusion. It is also used to implement synchronization between two processes. It is also used to implement synchronization between two threads.&lt;br&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;

&lt;h3&gt;&lt;strong&gt;8.what is spooling?&lt;/strong&gt; &lt;br&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Spooling&lt;/strong&gt; is a process that temporarily stores data in a buffer and sends it to a &lt;strong&gt;slow input/output device&lt;/strong&gt; in a continuous stream, making the system more efficient and responsive.&lt;br&gt;&lt;strong&gt;Often stored in physical memory&lt;/strong&gt;, buffers, or interrupts. &lt;strong&gt;FIFO is used to process the spool in ascending order.&lt;/strong&gt;&lt;/p&gt;
&lt;br&gt;
&lt;hr&gt;

&lt;h3&gt;&lt;strong&gt;9.what is thrashing?&lt;/strong&gt; &lt;br&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Thrash&lt;/strong&gt;  describe the poor performance of a virtual memory system when the same pages are loaded repeatedly owing to a shortage of &lt;strong&gt;main memory to store them in secondary memory.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;strong&gt;Thrashing&lt;/strong&gt; is when &lt;strong&gt;virtual memory resources&lt;/strong&gt; are &lt;strong&gt;overutilized&lt;/strong&gt;, resulting in a &lt;strong&gt;persistent state of paging and page faults&lt;/strong&gt;, which inhibits most &lt;strong&gt;application-level activity&lt;/strong&gt;. It causes the computer&amp;#39;s performance to decline or collapse. The scenario can last indefinitely unless the user stops certain running apps or active processes to free up &lt;strong&gt;extra virtual memory resources.&lt;/strong&gt;&lt;/p&gt;
&lt;br&gt;

&lt;p&gt;&lt;strong&gt;Page faults&lt;/strong&gt; and &lt;strong&gt;Swapping&lt;/strong&gt; are important factors in understanding thrashing. &lt;br&gt;&lt;br&gt;&lt;strong&gt;Page faults&lt;/strong&gt; a type of interrupt that occurs when a program attempts to access a page of memory that is not currently mapped to physical memory, leading to a disk I/O operation. &lt;br&gt;&lt;br&gt;&lt;strong&gt;Swapping&lt;/strong&gt; is the process of moving pages of memory from physical memory to disk and vice versa. &lt;br&gt; &lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;The above concepts have deeper implications in the field of Operating Systems. This post has only scratched the surface of the concepts. Each topic would be better understood if you go through the links provided in the references section. &lt;br&gt;&lt;br&gt;In subsequent post, if time permits, I would like to dive deeper into each question as a topic.&lt;/p&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://leetcode.com/discuss/interview-question/operating-system/3216693/INTRESTING-INTERVIEW-QUESTIONS-IN-OS&quot;&gt;leetcode&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.geeksforgeeks.org/kernel-in-operating-system/&quot;&gt;geeksforgeeks&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.techopedia.com/definition/3328/bootstrap&quot;&gt;TechOpedia&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://computer.howstuffworks.com/computer-run-without-operating-system.htm&quot;&gt;how Stuff Works&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.baeldung.com/java-mutex&quot;&gt;Baeldung&lt;/a&gt;,&lt;a href=&quot;https://www.baeldung.com/cs/semaphore&quot;&gt;SEMAPHORES&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.notesjam.com/2017/10/spooling-in-operating-system.html&quot;&gt;NOTESJAM&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Thrashing_(computer_science)#Other_uses&quot;&gt;WIKIPEDIA&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.i2tutorials.com/os-introduction/os-scheduling-criteria/&quot;&gt;I2Tutorial&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=VjPgYcQqqN0&amp;amp;list=PLBlnK6fEyqRiVhbXDGLXDk_OQAeuVcp2O&amp;amp;ab_channel=NesoAcademy&quot;&gt;NESO ACADEMY&lt;/a&gt; &lt;br&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>OS</category>
      <category>bootstrap</category>
      <category>ExecutorService</category>
      <category>Kernel</category>
      <category>mutex</category>
      <category>OS</category>
      <category>paging</category>
      <category>scheduling</category>
      <category>Semaphores</category>
      <category>spooling</category>
      <category>Thrashing</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/40</guid>
      <comments>https://codefast.tistory.com/40#entry40comment</comments>
      <pubDate>Tue, 28 Feb 2023 15:38:15 +0900</pubDate>
    </item>
    <item>
      <title>MANUAL INSTALLATION of ACS-7.2.0, ASS-2.x and Local T-Engine Service using distribution package</title>
      <link>https://codefast.tistory.com/39</link>
      <description>&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;p&gt;Refer specifications requirements and  &lt;a href=&quot;https://docs.alfresco.com/content-services/7.2/install/zip/&quot;&gt;supported platforms.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;NOTE: &lt;b&gt;THIS IS ABOUT ACS7 setup on Windows 10 x64 Platform &lt;/b&gt;&lt;/p&gt;
&lt;h2&gt;REQUIRED SOFTWARES&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://artifacts.alfresco.com/nexus/service/local/repositories/releases/content/org/alfresco/alfresco-content-services-community-distribution/7.2.0.1/alfresco-content-services-community-distribution-7.2.0.1.zip&quot;&gt;ACS-7.2.0 package (alfresco-content-services-community-distribution-7.2.0.1)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://download.alfresco.com/cloudfront/release/community/SearchServices/2.0.5/alfresco-search-services-2.0.5.zip&quot;&gt; ASS-2.0.3 package (alfresco-search-services-2.0.3.5)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.oracle.com/java/technologies/downloads/#java11&quot;&gt;Java: Oracle jdk-11.0.13&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tomcat.apache.org/download-90.cgi&quot;&gt;Tomcat: Tomcat 9.0.62&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://activemq.apache.org/components/classic/download/&quot;&gt;ActiveMQ: ActiveMQ v5.16.2.&lt;/a&gt; Mandatory for transformation services. Check this out for Local Transformation Service&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.postgresql.org/download/&quot;&gt;DB: PostgreSQL 13&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;--- &lt;a href=&quot;https://docs.alfresco.com/transform-service/latest/install/#prereq-non-containerized-deploy&quot;&gt;MANUAL INSTALLATION PROCESS  Documentations &lt;/a&gt;&lt;br&gt;7. ImageMagick: &lt;a href=&quot;https://download.imagemagick.org/archive/&quot;&gt;ImageMagick v7.1.0&lt;/a&gt;&lt;br&gt;8. Libreoffice: &lt;a href=&quot;https://www.libreoffice.org/download/download-libreoffice/&quot;&gt;LibreOffice v7.0.6&lt;/a&gt;&lt;br&gt;9. Alfresco &lt;a href=&quot;https://artifacts.alfresco.com/nexus/content/groups/public/org/alfresco/alfresco-transform-core-aio-boot/2.5.7/alfresco-transform-core-aio-boot-2.5.7.jar&quot;&gt;Transform Core AIO Boot App v2.5.7 &lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Type of deployment:&lt;/h3&gt;
&lt;p&gt;ACS, Share, ASS (SOLR6), and Local transformation services on same machine&lt;br&gt;Setup With Shared Secret (Without SSL)&lt;/p&gt;
&lt;p&gt;Let’s download all the required packages that we need for the setup.&lt;/p&gt;
&lt;p&gt;Note: Make sure you set the JAVA_HOME environment variable (on windows). It is the installation path of jdk. E.g. JAVA_HOME=C:\Program Files\Java\jdk-11.0.15&lt;/p&gt;
&lt;h3&gt;Optional Alfresco module packages (amps)-Useful for admins/developers:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://repo1.maven.org/maven2/org/orderofthebee/support-tools/support-tools-repo/1.1.0.0/support-tools-repo-1.1.0.0-amp.amp&quot;&gt;support-tools-repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://repo1.maven.org/maven2/org/orderofthebee/support-tools/support-tools-share/1.1.0.0/support-tools-share-1.1.0.0-amp.amp&quot;&gt;support-tools-share&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/abhinavmishra14/js-console/releases/download/0.7-rc/javascript-console-repo-0.7.amp&quot;&gt;javascript-console-repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/abhinavmishra14/js-console/releases/download/0.7-rc/javascript-console-share-0.7.amp&quot;&gt;javascript-console-share&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;DB Setup POSTGRESQL 13&lt;/h3&gt;
&lt;p&gt;Ensure postgres is running on port 5432. If not, change the port in postgresql.conf file and restart the service.&lt;br&gt;Create a database named alfresco and a user named alfresco with password alfresco. &lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;create role alfresco LOGIN password &amp;#39;alfresco&amp;#39;;

create database alfresco encoding &amp;#39;utf8&amp;#39;;

grant all on database alfresco to alfresco;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;ACS Setup&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create a folder ACS-7.2.0 and extract the above ACS Download package in it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a folder named alf_data in ACS-7.2.0 folder.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create folder tomcat in ACS-7.2.0 folder and extract the tomcat package in it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set environment variables for ACS-7.2.0 folder (eg. ALF_HOME)  . Helpful for apply_amps.bat, clean_tomcat.bat&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy downloads ACS-7.2.0\keystore into ACS-7.2.0\alf_data\keystore&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy amps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy contents from downloads ACS-7.2.0\amps into  ACS-7.2.0\amps. &lt;/li&gt;
&lt;li&gt;Optional: Copy support-tools-repo.amp into ACS-7.2.0\amps, support-tools-share.amp into ACS-7.2.0\amps_share, javascript-console-repo.amp into ACS-7.2.0\amps, javascript-console-share.amp into  ACS-7.2.0\amps&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy download ACS-7.2.0\bin” into “ACS-7.2.0\bin” directory &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Licenses: Copy the contents from “ACS-7.2.0\licenses” into “ACS-7.2.0\licenses” directory. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ACS TOMCAT:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy the contents from download “ACS-7.2.0\web-server\conf” into “ACS-7.2.0\tomcat\conf” folder. &lt;/li&gt;
&lt;li&gt;Copy the contents from download “ACS-7.2.0\web-server\lib\” into “ACS-7.2.0\tomcat\lib\” folder. &lt;/li&gt;
&lt;li&gt;Copy the contents from download “ACS-7.2.0\web-server\shared\classes” into “ACS-7.2.0\tomcat\shared\classes\” folder.  &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Encryption keystore config:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Create a new directory named &amp;#39;keystore&amp;#39; under &amp;#39;ACS-7.2.0\tomcat\shared\classes\alfresco\extension&amp;#39; directory. We need to copy the &amp;#39;metadata-keystore&amp;#39; related configs in this newly created directory.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy the &amp;#39;metadata-keystore&amp;#39; directory from downloads &amp;#39;ACS-7.2.0\keystore\metadata-keystore&amp;#39; to &amp;#39;ACS-7.2.0\tomcat\shared\classes\alfresco\extension\keystore&amp;#39; &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SET environment variable  for meta-data JAVA_TOOL_OPTIONS=&amp;quot;-Dencryption.keystore.type=JCEKS -Dencryption.cipherAlgorithm=DESede/CBC/PKCS5Padding -Dencryption.keyAlgorithm=DESede -Dencryption.keystore.location=&lt;code&gt;&amp;lt;REPLACE-ACS-7.2.0&amp;gt;&lt;/code&gt;\tomcat\shared\classes\alfresco\extension\keystore\metadata-keystore\keystore -Dmetadata-keystore.password=mp6yc0UD9e -Dmetadata-keystore.aliases=metadata -Dmetadata-keystore.metadata.password=oKIWzVdEdA -Dmetadata-keystore.metadata.algorithm=DESede&amp;quot;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete all files/folders from “ACS-7.2.0\tomcat\webapps”.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Copy the contents from downloads “ACS-7.2.0\web-server\webapps” into “ACS-7.2.0\tomcat\webapps\” folder.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delete all files/folders from “ACS-7.2.0\tomcat\work\Catalina\localhost” if there are any.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open and edit server.xml file which can be found under: “ACS-7.2.0\tomcat\conf” directory [Full path: ACS-7.2.0\tomcat\conf\server.xml]:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Find Connector with port &amp;quot;8080”. Add the URIEncoding and maxHttpHeaderSize attributes.&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;Connector port=&amp;quot;8080&amp;quot; protocol=&amp;quot;HTTP/1.1&amp;quot;
URIEncoding=&amp;quot;UTF-8&amp;quot; connectionTimeout=&amp;quot;20000&amp;quot;
maxHttpHeaderSize=&amp;quot;32768&amp;quot;
redirectPort=&amp;quot;8443&amp;quot; /&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open and edit the ACS-7.2.0\tomcat\conf\catalina.properties file:&lt;br&gt;Update the value of the shared.loader= property to the following:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We need to add JAVA_TOOL_OPTIONS java environment variable for metadata encryption, we had copied the keystore under &amp;#39;ACS-7.2.0\tomcat\shared\classes\alfresco\extension\keystore\metadata-keystore&amp;#39; directory already. Check the steps above. Open and edit ACS-7.2.0\tomcat\bin\catalina.bat . Add the variable after JAVA_OPTS in catalina.bat file. If you add this variable at the end of the file, it is not getting recognized for some reason. So make sure you add the variable before JAVA_OPTS as mentioned above. See the example screenshot below for reference or check here.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;rem ACS72 Custom changes [Start] ##############
set &amp;quot;JAVA_TOOL_OPTIONS=-Dencryption.keystore.type=JCEKS -Dencryption.cipherAlgorithm=DESede/CBC/PKCS5Padding -Dencryption.keyAlgorithm=DESede -Dencryption.keystore.location=C:\alfresco-community72\tomcat\shared\classes\alfresco\extension\keystore\metadata-keystore\keystore -Dmetadata-keystore.password=mp6yc0UD9e -Dmetadata-keystore.aliases=metadata -Dmetadata-keystore.metadata.password=oKIWzVdEdA -Dmetadata-keystore.metadata.algorithm=DESede&amp;quot;
rem ACS72 Custom changes [End] ##############&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rename “ACS-7.2.0\tomcat\shared\classes\alfresco-global.properties.sample” to “alfresco-global.properties”&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open and edit “ACS-7.2.0\tomcat\shared\classes\alfresco-global.properties” and add the following configuration properties:&lt;/li&gt;
&lt;li&gt;Add the “dir.root” property as path to alf_data folder and add &amp;#39;dir.keystore&amp;#39; property to the above copied encryption keystore path&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;dir.root={PERONSAL_DIRECTORY/ACS-7.2.0}/alf_data
dir.keystore={PERONSAL_DIRECTORY/ACS-7.2.0}/tomcat/shared/classes/alfresco/extension/keystore&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add alfresco and share host, port, context and protocol specific properties. For more details see: &lt;a href=&quot;https://docs.alfresco.com/content-services/latest/config/#using-alfresco-globalproperties&quot;&gt;https://docs.alfresco.com/content-services/latest/config/#using-alfresco-globalproperties&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;alfresco.context=alfresco&lt;br&gt;alfresco.host=${localname}&lt;br&gt;alfresco.port=8080&lt;br&gt;alfresco.protocol=http&lt;br&gt;share.context=share&lt;br&gt;share.host=${localname}&lt;br&gt;share.port=8080&lt;br&gt;share.protocol=http&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;19. Add the database connection properties which alfresco will use to create a JDBC connection with db. Use the db name and credentials when we prepared the database.
```properties
db.driver=org.postgresql.Driver
db.username=alfresco
db.password=alfresco
db.name=alfresco
db.url=jdbc:postgresql://localhost:5432/${db.name}
db.pool.max=275
db.pool.validate.query=SELECT 1
#Add the server mode property, leave it default to ‘UNKNOWN’.
system.serverMode=UNKNOWN
#Add the alfresco rmi services port and host properties.
alfresco.rmi.services.port=50500
alfresco.rmi.services.host=0.0.0.0&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;T-Service Configuration&lt;/h3&gt;
&lt;p&gt;To set up Local transformation service, we need to install Imagemagick, Libreoffice and AlfrescoPDFRenderer locally and executables will be used by transformation service spring boot application.&lt;br&gt;Extract binaries from the downloads folder and copy them to the following locations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ACS-7.2.0\imagemagick&lt;/li&gt;
&lt;li&gt;ACS-7.2.0\libreoffice&lt;/li&gt;
&lt;li&gt;ACS-7.2.0\activemq&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Alfresco PDF Renderer Setup:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Extract the alfresco-pdf-renderer-2.1.0.zip file from the downloads folder and copy the alfresco-pdf-renderer-2.1.0 folder to ACS-7.2.0\alfresco-pdf-renderer-2.1.0 directory. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new directory named &amp;#39;exiftool&amp;#39; under &amp;quot;C:\alfresco-community72&amp;quot; Extract to &amp;quot;ACS-7.2.0\exiftool&amp;quot;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set the exiftool directory to Windows PATH Environment Variable: %ALF_HOME%\exiftool&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update alfresco-global.properties to enable transformation service:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Open and edit “ACS-7.2.0\tomcat\shared\classes\alfresco-global.properties”&lt;br&gt;Enable local transformation service (its enabled by default but just FYI here):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;localTransform.core-aio.url=http://localhost:8090/
#This property is default true, here it it for information purpose.
local.transform.service.enabled=true

#Add the activemq url property and enabled messaging subsystem. It will be used when you setup transformation service.
messaging.broker.url=tcp://localhost:61616

#This property is default true, here it it for information purpose.
messaging.subsystem.autoStart=true

#If you have setup username and password for AMQ, then set the below properties. In my case I have kept default admin/admin
messaging.broker.username=admin
messaging.broker.password=admin&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Copy the downloaded transform-core-aio-boot jar file to &amp;#39;ACS-7.2.0\bin&amp;quot; directory.&lt;/p&gt;
&lt;h3&gt;Transformation Service EXECUTIONS:&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;java -DPDFRENDERER_EXE=&amp;quot;{ACS-7.2.0}\alfresco-pdf-renderer\alfresco-pdf-renderer.exe&amp;quot; -DLIBREOFFICE_HOME=&amp;quot;{ACS-7.2.0}\libreoffice&amp;quot; -DIMAGEMAGICK_ROOT=&amp;quot;{ACS-7.2.0}\imagemagick&amp;quot; -DIMAGEMAGICK_DYN=&amp;quot;{ACS-7.2.0}\imagemagick\lib&amp;quot; -DIMAGEMAGICK_CODERS=&amp;quot;{ACS-7.2.0}\imagemagick\modules\coders&amp;quot; -DIMAGEMAGICK_CONFIG=&amp;quot;{ACS-7.2.0}\imagemagick&amp;quot; -DIMAGEMAGICK_EXE=&amp;quot;{ACS-7.2.0}\imagemagick\convert.exe&amp;quot; -DACTIVEMQ_URL=tcp://localhost:61616 -jar {ACS-7.2.0}\bin\alfresco-transform-core-aio-boot-2.5.7.jar&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Verify Transformation Service:&lt;/h3&gt;
&lt;p&gt;transformation service at &lt;a href=&quot;http://localhost:8090&quot;&gt;http://localhost:8090&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Update alfresco-global.properties to add other misc. properties:&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;#Add property for email notification on invite, it is by default disabled.
notification.email.siteinvite=false
Add the license location property.
### License location ###
dir.license.external=C:/alfresco-community72
#Add following properties related to security, smart folder and JMX. All values are default out-of-the-box
security.anyDenyDenies=false
smart.folders.enabled=false
alfresco.jmx.connector.enabled=false&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Logging Configuration&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Go to {ACS-7.2.0}\tomcat\shared\classes\alfresco\extension\ folder and rename “custom-log4j.properties.sample” to “custom-log4j.properties”&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Apply amps to alfresco.war and share.war:&lt;/h2&gt;
&lt;p&gt;NOTE: &lt;b&gt;Mandatory Amps&lt;/b&gt;&lt;br&gt;Execute &amp;#39;apply_amps.bat&amp;#39; script to apply amps, it will install amps copied under {ACS-7.2.0}\amps and C:\alfresco-community72\amps_share directories to alfresco.war and share.war.&lt;br&gt;Open windows command prompt&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Go to {ACS-7.2.0}\bin path&lt;/li&gt;
&lt;li&gt;Execute the &amp;#39;apply_amps.bat&amp;#39;&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;./apply_amps.bat&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Share Config Custom Changes&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;repository-url&amp;gt;http://localhost:8080/alfresco &amp;lt;/repository-url&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Make sure you update the share &amp;quot;Remote&amp;quot; configuration to point to the alfresco host and port, in case you are setting up alfresco and share on different servers. Default values are &amp;quot;localhost&amp;quot; and &amp;quot;8080&amp;quot;. We are setting up both ACS and Share on same host so we will leave it default.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;config evaluator=&amp;quot;string-compare&amp;quot; condition=&amp;quot;Remote&amp;quot;&amp;gt;
&amp;lt;remote&amp;gt;
&amp;lt;endpoint&amp;gt;
&amp;lt;id&amp;gt;alfresco-noauth&amp;lt;/id&amp;gt;
&amp;lt;name&amp;gt;Alfresco - unauthenticated access&amp;lt;/name&amp;gt;
&amp;lt;description&amp;gt;Access to Alfresco Repository WebScripts that do not require authentication&amp;lt;/description&amp;gt;
&amp;lt;connector-id&amp;gt;alfresco&amp;lt;/connector-id&amp;gt;
&amp;lt;endpoint-url&amp;gt;http://localhost:8080/alfresco/s&amp;lt;/endpoint-url&amp;gt;
&amp;lt;identity&amp;gt;none&amp;lt;/identity&amp;gt;
&amp;lt;/endpoint&amp;gt;

         &amp;lt;endpoint&amp;gt;
            &amp;lt;id&amp;gt;alfresco&amp;lt;/id&amp;gt;
            &amp;lt;name&amp;gt;Alfresco - user access&amp;lt;/name&amp;gt;
            &amp;lt;description&amp;gt;Access to Alfresco Repository WebScripts that require user authentication&amp;lt;/description&amp;gt;
            &amp;lt;connector-id&amp;gt;alfresco&amp;lt;/connector-id&amp;gt;
            &amp;lt;endpoint-url&amp;gt;http://localhost:8080/alfresco/s&amp;lt;/endpoint-url&amp;gt;
            &amp;lt;identity&amp;gt;user&amp;lt;/identity&amp;gt;
         &amp;lt;/endpoint&amp;gt;

         &amp;lt;endpoint&amp;gt;
            &amp;lt;id&amp;gt;alfresco-feed&amp;lt;/id&amp;gt;
            &amp;lt;name&amp;gt;Alfresco Feed&amp;lt;/name&amp;gt;
            &amp;lt;description&amp;gt;Alfresco Feed - supports basic HTTP authentication via the EndPointProxyServlet&amp;lt;/description&amp;gt;
            &amp;lt;connector-id&amp;gt;http&amp;lt;/connector-id&amp;gt;
            &amp;lt;endpoint-url&amp;gt;http://localhost:8080/alfresco/s&amp;lt;/endpoint-url&amp;gt;
            &amp;lt;basic-auth&amp;gt;true&amp;lt;/basic-auth&amp;gt;
            &amp;lt;identity&amp;gt;user&amp;lt;/identity&amp;gt;
         &amp;lt;/endpoint&amp;gt;

         &amp;lt;endpoint&amp;gt;
            &amp;lt;id&amp;gt;alfresco-api&amp;lt;/id&amp;gt;
            &amp;lt;parent-id&amp;gt;alfresco&amp;lt;/parent-id&amp;gt;
            &amp;lt;name&amp;gt;Alfresco Public API - user access&amp;lt;/name&amp;gt;
            &amp;lt;description&amp;gt;Access to Alfresco Repository Public API that require user authentication.
                         This makes use of the authentication that is provided by parent &amp;#39;alfresco&amp;#39; endpoint.&amp;lt;/description&amp;gt;
            &amp;lt;connector-id&amp;gt;alfresco&amp;lt;/connector-id&amp;gt;
            &amp;lt;endpoint-url&amp;gt;http://localhost:8080/alfresco/api&amp;lt;/endpoint-url&amp;gt;
            &amp;lt;identity&amp;gt;user&amp;lt;/identity&amp;gt;
         &amp;lt;/endpoint&amp;gt;
      &amp;lt;/remote&amp;gt;
   &amp;lt;/config&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Alfresco Config Custom Changes (share where user search doesn&amp;#39;t work changes)&lt;/h3&gt;
&lt;p&gt;There is a known issue with share where user search doesn&amp;#39;t work. For more info see these issues (The issue still persist in Share 7):&lt;br&gt;&lt;a href=&quot;https://github.com/Alfresco/acs-community-packaging/issues/367&quot;&gt;https://github.com/Alfresco/acs-community-packaging/issues/367&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://github.com/Alfresco/acs-community-deployment/issues/85&quot;&gt;https://github.com/Alfresco/acs-community-deployment/issues/85&lt;/a&gt;&lt;br&gt;Find the &lt;show-authorization-status&gt;true&lt;/show-authorization-status&gt; tag and change the value to &amp;#39;false&amp;#39;,&lt;br&gt;Update {ACS-7.2.0}\tomcat\shared\classes\alfresco\web-extension\share-config-custom.xml&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;
&amp;lt;config evaluator=&amp;quot;string-compare&amp;quot; condition=&amp;quot;Users&amp;quot; replace=&amp;quot;true&amp;quot;&amp;gt;
&amp;lt;users&amp;gt;
&amp;lt;!-- minimum length for username and password --&amp;gt;
&amp;lt;username-min-length&amp;gt;2&amp;lt;/username-min-length&amp;gt;
&amp;lt;password-min-length&amp;gt;3&amp;lt;/password-min-length&amp;gt;
&amp;lt;!-- Default value is &amp;#39;true&amp;#39;, setting it to &amp;#39;false&amp;#39; to fix the user search issue. --&amp;gt;
&amp;lt;show-authorization-status&amp;gt;false&amp;lt;/show-authorization-status&amp;gt;
&amp;lt;/users&amp;gt;
&amp;lt;!-- This enables/disables the Add External Users Panel on the Add Users page. --&amp;gt;
&amp;lt;enable-external-users-panel&amp;gt;false&amp;lt;/enable-external-users-panel&amp;gt;
&amp;lt;/config&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Setup and Configure ASS (Alfresco Search Services):&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Download and unzip alfresco-search-services-2.0.3.5.zip&lt;/li&gt;
&lt;li&gt;Copy the extracted folder “alfresco-search-services” to e.g. {ASS}.&lt;/li&gt;
&lt;li&gt;Open “{ACS-7.2.0}\tomcat\shared\classes\alfresco-global.properties” and add the following configuration properties:&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;solr.host=localhost
solr.port=8983
solr.secureComms=secret #Possible values are: secret, https
solr.sharedSecret=secret
solr.base.url=/solr
index.subsystem.name=solr6&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: We are setting up solr6 without SSL and with shared secret, hence using non SSL port and setting secureComms property as secret.&lt;/p&gt;
&lt;h2&gt;Optional&lt;/h2&gt;
&lt;h4&gt;enabling the multi language search support, Its optional if you wish to enable it. By default it is disabled. Open “{ASS}\solrhome\conf\shared.properties” and update following:&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;alfresco.cross.locale.datatype.0={http://www.alfresco.org/model/dictionary/1.0}text
alfresco.cross.locale.datatype.1={http://www.alfresco.org/model/dictionary/1.0}content
alfresco.cross.locale.datatype.2={http://www.alfresco.org/model/dictionary/1.0}mltext
#enabling search suggestions “{ASS}\solrhome\conf\shared.properties” 
alfresco.suggestable.property.0={http://www.alfresco.org/model/content/1.0}name
alfresco.suggestable.property.1={http://www.alfresco.org/model/content/1.0}title
alfresco.suggestable.property.2={http://www.alfresco.org/model/content/1.0}description
alfresco.suggestable.property.3={http://www.alfresco.org/model/content/1.0}content&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More details on shared.properties can be found here: &lt;a href=&quot;https://docs.alfresco.com/search-services/latest/install/options/&quot;&gt;https://docs.alfresco.com/search-services/latest/install/options/&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;If you would setup search services on a different or remote machine, you would need to set the SOLR_SOLR_HOST, SOLR_SOLR_PORT, SOLR_SOLR_BASEURL, SOLR_ALFRESCO_HOST, SOLR_ALFRESCO_PORT and SOLR_ALFRESCO_BASEURL environment variables. This is optional but we will keep the mapping for future reference.&lt;/h5&gt;
&lt;p&gt;We are setting up without SSL, so set this variable SOLR_ALFRESCO_SECURECOMMS to secret. It is mandatory as default value is https. And Set the &amp;#39;JAVA_TOOL_OPTIONS&amp;#39; variable to pass the JVM arguments for Solr and Alfresco shared secret communication mechanism. Open “{ASS}\solr.in.cmd” file and add following at the end of the file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;set SOLR_SOLR_HOST=localhost
set SOLR_SOLR_PORT=8983
set SOLR_SOLR_BASEURL=/solr
set SOLR_ALFRESCO_HOST=localhost
set SOLR_ALFRESCO_PORT=8080
set SOLR_ALFRESCO_BASEURL=/alfresco

:: Since we are setting up with no SSL and shared secret, this property need to be set to secret. Default is https
set SOLR_ALFRESCO_SECURECOMMS=secret

rem ACS72 shared secret changes [Start] ##############
set JAVA_TOOL_OPTIONS=-Dalfresco.secureComms.secret=secret

rem ############ OR Instead of JAVA_TOOL_OPTIONS, you can also export SOLR_OPTS , example below. Make sure you dont export both###
rem set SOLR_OPTS=-Dalfresco.secureComms.secret=secret

rem ACS72 shared secret changes [End] ##############&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also set SOLR_HOME variable in solr.in.cmd (if you see error like  ERROR: Solr home directory {ASSS} must contain solr.xml,  then this setting is must)&lt;br&gt;set SOLR_HOME={ASS}\solrhome&lt;br&gt;Alternatively you can set the properties in “{ASS}\solrhome\templates\rerank\conf\solrcore.properties” file as well before cores are created. If you have both alfresco and archive cores already created use the environment variable based approach. Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;
alfresco.host=localhost
alfresco.port=8080
alfresco.port.ssl=8443
alfresco.baseUrl=/alfresco
# secret, https
alfresco.secureComms=secret&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For all the externalized search service configurations (environment variables), visit: &lt;a href=&quot;https://docs.alfresco.com/search-services/latest/config/#search-services-externalized-configuration&quot;&gt;https://docs.alfresco.com/search-services/latest/config/#search-services-externalized-configuration&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can use the &lt;a href=&quot;https://chrome.google.com/webstore/detail/modheader-modify-http-hea/idgpnmonknjnojddfkpgkljpfnnfcklj&quot;&gt;modheader browser&lt;/a&gt; extension to pass the header info,&lt;br&gt;Now we are done with all the setup and config changes. Here are full “alfresco-global.properties”, “custom-log4j.properties”, “shared.properties” , “solr.in.cmd”, &amp;quot;solrcore.properties&amp;quot; files for reference:&lt;/p&gt;
&lt;p&gt;alfresco-global.properties:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;###############################
## Common Alfresco Properties #
###############################


dir.root={ACS-7.2.0}/alf_data
dir.contentstore=${dir.root}/contentstore
dir.contentstore.deleted=${dir.root}/contentstore.deleted


#
# Encryption properties
#
# default keystores location is now this, it was changed from previous versions
# for more details see: https://docs.alfresco.com/content-services/latest/admin/security/#alfresco-keystore-configuration
dir.keystore={ACS-7.2.0}/tomcat/shared/classes/alfresco/extension/keystore

#
# URL Generation Parameters (The ${localname} token is replaced by the local server name)
#-------------
alfresco.context=alfresco
alfresco.host=${localname}
alfresco.port=8080
alfresco.protocol=http
share.context=share
share.host=${localname}
share.port=8080
share.protocol=http

### database connection properties ###
db.driver=org.postgresql.Driver
db.username=alfresco
db.password=alfresco
db.name=alfresco
db.url=jdbc:postgresql://localhost:5432/${db.name}
# Note: your database must also be able to accept at least this many connections.  Please see your database documentation for instructions on how to configure this.
db.pool.max=275
db.pool.validate.query=SELECT 1

# The server mode. Set value here
# UNKNOWN | TEST | BACKUP | PRODUCTION
system.serverMode=UNKNOWN

### RMI registry port for JMX ###
alfresco.rmi.services.port=50500

# Default value of alfresco.rmi.services.host is 0.0.0.0 which means &amp;#39;listen on all adapters&amp;#39;.
# This allows connections to JMX both remotely and locally.
alfresco.rmi.services.host=0.0.0.0

#
#
# Assign individual ports for each service for best performance
# or run several services on the same port. You can even run everything on 50500 if needed.
# Select 0 to use a random unused port.
#monitor.rmi.service.port=50508


### E-mail site invitation setting ###
notification.email.siteinvite=false

### License location ###
dir.license.external={ACS-7.2.0}

### Allow extended ResultSet processing
security.anyDenyDenies=false

### Smart Folders Config Properties ###
smart.folders.enabled=false

### Remote JMX (Default: disabled) ###
alfresco.jmx.connector.enabled=false

## AMQ And Transformation services
localTransform.core-aio.url=http://localhost:8090/
local.transform.service.enabled=true
messaging.broker.url=tcp://localhost:61616
messaging.subsystem.autoStart=true
#If you have setup username and password for AMQ, then set the below properties. In my case I have kept default admin/admin
messaging.broker.username=admin
messaging.broker.password=admin

################ Solr Search service configurations ###############

#
# Index Recovery Mode
#-------------
#index.recovery.mode=AUTO

# Set this property unless you have explicitly chosen to expose some repository APIs without authentication
solr.host=localhost
solr.port=8983
#secret, https
solr.secureComms=secret
solr.sharedSecret=secret
solr.base.url=/solr
index.subsystem.name=solr6&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;custom-log4j.properties:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;#Tranformer specific logs
log4j.logger.org.alfresco.repo.content.transform.TransformerDebug=info
log4j.logger.org.alfresco.util.exec.RuntimeExecBootstrapBean=info
log4j.logger.org.alfresco.util.exec.RuntimeExec=info

#ScriptLogger
log4j.logger.org.alfresco.repo.jscript.ScriptLogger=debug

#Log for email executer
log4j.logger.org.alfresco.repo.action.executer.MailActionExecuter=info

#Transaction specific logs
log4j.logger.org.alfresco.repo.transaction.RetryingTransactionHelper=info

#Solr specific logs
log4j.logger.org.alfresco.solr.query.AbstractQParser=debug
log4j.logger.org.alfresco.repo.search.impl.solr.SolrQueryHTTPClient=debug

#Metadata extractor
log4j.logger.org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter=info
log4j.logger.org.alfresco.repo.content.metadata.MetadataExtracterRegistry=info

#Thumbnail logs
log4j.logger.org.alfresco.repo.thumbnail=info

# FTP server debugging
log4j.logger.org.alfresco.ftp.protocol=info
log4j.logger.org.alfresco.ftp.server=info&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;shared.properties:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;# Shared Properties file

#Host details an external client would use to connect to Solr
solr.host=localhost
#If not set then solr.port will be the jetty.port
#solr.port=8983
solr.baseurl=/solr

# Properties treated as identifiers when indexed

alfresco.identifier.property.0={http://www.alfresco.org/model/content/1.0}creator
alfresco.identifier.property.1={http://www.alfresco.org/model/content/1.0}modifier
alfresco.identifier.property.2={http://www.alfresco.org/model/content/1.0}userName
alfresco.identifier.property.3={http://www.alfresco.org/model/content/1.0}authorityName
alfresco.identifier.property.4={http://www.alfresco.org/model/content/1.0}lockOwner

# Suggestable Properties
alfresco.suggestable.property.0={http://www.alfresco.org/model/content/1.0}name
alfresco.suggestable.property.1={http://www.alfresco.org/model/content/1.0}title
alfresco.suggestable.property.2={http://www.alfresco.org/model/content/1.0}description
alfresco.suggestable.property.3={http://www.alfresco.org/model/content/1.0}content

# Data types that support cross locale/word splitting/token patterns if tokenised
alfresco.cross.locale.property.0={http://www.alfresco.org/model/content/1.0}name
alfresco.cross.locale.property.1={http://www.alfresco.org/model/content/1.0}lockOwner

# Data types that support cross locale/word splitting/token patterns if tokenised
alfresco.cross.locale.datatype.0={http://www.alfresco.org/model/dictionary/1.0}text
alfresco.cross.locale.datatype.1={http://www.alfresco.org/model/dictionary/1.0}content
alfresco.cross.locale.datatype.2={http://www.alfresco.org/model/dictionary/1.0}mltext

alfresco.model.tracker.cron=0/10 * * * * ? *

# Whether path queries are enabled.
alfresco.cascade.tracker.enabled=true&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;solr.in.cmd:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;@echo off

REM Increase Java Min/Max Heap as needed to support your indexing / query needs
set SOLR_JAVA_MEM=-Xms2g -Xmx2g

REM Alfresco configuration. This file is automatically included by solr. You can define your custom settings here
set SOLR_OPTS=%SOLR_OPTS% -Dsolr.jetty.request.header.size=1000000 -Dsolr.jetty.threads.stop.timeout=300000 -Ddisable.configEdit=true

REM Location where Solr should write logs to. Absolute or relative to solr start dir
set SOLR_LOGS_DIR=..\..\logs
set LOG4J_CONFIG=file:!SOLR_LOGS_DIR!\log4j.properties


set SOLR_SOLR_HOST=localhost
set SOLR_SOLR_PORT=8983
set SOLR_SOLR_BASEURL=/solr
set SOLR_ALFRESCO_HOST=localhost
set SOLR_ALFRESCO_PORT=8080
set SOLR_ALFRESCO_BASEURL=/alfresco

:: Since we are setting up with no SSL, this property need to be set to secret. Default is https
set SOLR_ALFRESCO_SECURECOMMS=secret

rem ACS72 shared secret changes [Start] ##############
set JAVA_TOOL_OPTIONS=-Dalfresco.secureComms.secret=secret

rem ############ OR Instead of JAVA_TOOL_OPTIONS, you can also export SOLR_OPTS , example below. Make sure you dont export both###
rem set SOLR_OPTS=-Dalfresco.secureComms.secret=secret

rem ACS72 shared secret changes [End] ##############
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;solrcore.properties (Highlighting important properties only):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-properties&quot;&gt;alfresco.host=localhost
alfresco.port=8080
alfresco.port.ssl=8443
alfresco.baseUrl=/alfresco

# secret, https
alfresco.secureComms=secret&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;START AND TEST&lt;/h3&gt;
&lt;p&gt;There are three services that we need to start one by one in order:&lt;/p&gt;
&lt;h2&gt;ActiveMQ&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;{ACS-7.2.0}\activemq\bin\win64\activemq.bat start&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;localTransformationService&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;     java -DPDFRENDERER_EXE=&amp;quot;{ACS-7.2.0}\alfresco-pdf-renderer\alfresco-pdf-renderer.exe&amp;quot; -DLIBREOFFICE_HOME=&amp;quot;{ACS-7.2.0}\libreoffice&amp;quot; -DIMAGEMAGICK_ROOT=&amp;quot;{ACS-7.2.0}\imagemagick&amp;quot; -DIMAGEMAGICK_DYN=&amp;quot;{ACS-7.2.0}\imagemagick&amp;quot; -DIMAGEMAGICK_CODERS=&amp;quot;{ACS-7.2.0}\imagemagick\modules\coders&amp;quot; -DIMAGEMAGICK_CONFIG=&amp;quot;{ACS-7.2.0}\imagemagick&amp;quot; -DIMAGEMAGICK_EXE=&amp;quot;{ACS-7.2.0}\imagemagick\convert.exe&amp;quot; -DACTIVEMQ_URL=tcp://localhost:61616?timeout=3000 -jar {ACS-7.2.0}\bin\alfresco-transform-core-aio-boot-2.5.7.jar&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Start DB&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;start “postgresql-x64-13” service.&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;{PostgreSQL_DIR}\13\bin\pg_ctl.exe start -D “C:\PostgreSQL\13\data&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Alfresco&lt;/h2&gt;
&lt;/li&gt;
&lt;li&gt;“{ACS-7.2.0}\tomcat\bin” and execute following command: &lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;catalina.bat start&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Or navigate to “{ACS-7.2.0}\tomcat\bin” folder and execute &lt;pre&gt;&lt;code&gt;startup.bat&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Solr6&lt;/h2&gt;
&lt;p&gt;To start SOLR6, use the following command by navigating to “{ASS}\solr\bin” folder via command prompt:&lt;/p&gt;
&lt;h3&gt;Initial start only&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;{ASS}\solr\bin\solr.cmd start -a &amp;quot;-Dcreate.alfresco.defaults=alfresco,archive&amp;quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Consecutive start command:&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;{ASS}\solr\bin\solr.cmd start&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;IMPORTANT: Notice&lt;/h3&gt;
&lt;p&gt;Any variable in curly braces (e.g. {ACS-7.2.0},{ASS}) should be replaced with the actual path of the folder used personally.&lt;/p&gt;
&lt;h2&gt;REFERENCE SITES&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.alfresco.com/content-services/7.2/install/zip/&quot;&gt;ALFRESCO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javaworld-abhinav.blogspot.com/2022/05/setup-acs-7-ass-2-and-local-windows.html&quot;&gt;EXPECT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Java</category>
      <category>activemq</category>
      <category>Alfresco</category>
      <category>Engine</category>
      <category>JMX</category>
      <category>opensource</category>
      <category>search</category>
      <category>secureComms</category>
      <category>solr</category>
      <category>Transaction</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/39</guid>
      <comments>https://codefast.tistory.com/39#entry39comment</comments>
      <pubDate>Tue, 28 Feb 2023 13:40:05 +0900</pubDate>
    </item>
    <item>
      <title>onlyoffice for alfresco 7.2.X | 7.3.X</title>
      <link>https://codefast.tistory.com/38</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://www.onlyoffice.com/office-for-alfresco.aspx&quot;&gt;ONLYOFFICE site&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;provides an installation video for linux/docker but this intallation process might sometimes fail.&lt;/p&gt;
&lt;p&gt;A better installation process for onlyoffice-alfresco is also provided on the github project level. But proper parameters for&lt;br&gt;this installation is missing(In regard to how to configure the Alfresco-ONLY-office Admin) page.&lt;/p&gt;
&lt;h2&gt;Guide to Install onlyoffice for alfresco 7.3 ?&lt;/h2&gt;
&lt;p&gt;The best reference to the &lt;a href=&quot;https://github.com/onlyoffice/onlyoffice-alfresco/releases&quot;&gt;git repo&lt;/a&gt; which provides the recent release version &lt;strong&gt;v6.0.1&lt;/strong&gt;&lt;br&gt;is much compatible with recent versions of alfresco 7.2.x or 7.3.x.&lt;/p&gt;
&lt;h5&gt;OLDER ALFRESCO SDK compatibility with ONLYOFFICE 6.0.1 versions was not tested&lt;/h5&gt;
&lt;p&gt;Our goal is to get alfresco &lt;strong&gt;7.2.x or 7.3.x&lt;/strong&gt; working with the &lt;strong&gt;onlyoffice v6.0.1&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;INSTALLATION PROCEDURE&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/ONLYOFFICE/onlyoffice-alfresco&quot;&gt;onlyoffice-alfresco&lt;/a&gt; provides installation guide but in this case our main goal is to get only office working in alfresco with the minimum effort.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Download the jars&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ONLYOFFICE/onlyoffice-alfresco/releases/download/v6.0.1/onlyoffice-integration-repo.jar&quot;&gt;REPO JAR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;- Copy the downloaded jar into {TOMCAT}/webapps/alfresco/WEB-INF/lib/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/ONLYOFFICE/onlyoffice-alfresco/releases/download/v6.0.1/onlyoffice-integration-share.jar&quot;&gt;SHARE JAR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;- Copy the downloaded jar into {TOMCAT}/webapps/share/WEB-INF/lib/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stop alfresco and restart&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NOTE: Does not matter how you stop your ?(running) alfresco.&lt;/li&gt;
&lt;li&gt;Ensure the jars are existing in the lib directory after restart.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check if only office exist&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can observe if the .jars executed properly with the alfresco&lt;/li&gt;
&lt;li&gt;From the alfresco admin page we can see the new config added &lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/alfresco-config.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;IMPORTANT: Configure Alfresco to connect to ONLYOFFICE SERVER&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/configer-details.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;It is very important to configure correctly&lt;/h5&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Document editing service address&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Secret key [NOTE] : &lt;strong&gt;ONLY office uses JWT tokens to authenticate users&lt;/strong&gt; Access to the document SERVER.&lt;br&gt;This can be left empty if &lt;strong&gt;NO JWT authentication&lt;/strong&gt; is enabled.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The editing service is also important and its runs with the other document service like the converter service.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, the address for the internal request. which means the base url to the alfresco instance.&lt;br&gt;NOTE: Errors in this configuration would show an alert error.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Failure to connect to the server&lt;/li&gt;
&lt;li&gt;Editing service connecting error&lt;/li&gt;
&lt;li&gt;Authentication error if JWT secret is wrong&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;SUCCESS Connection inspection&lt;/h5&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/success-connect.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If the connection to the document server was successful we expect to see the alert(success) after clicking save button.&lt;/p&gt;
&lt;p&gt;If any configuration is wrong this might not connect to the server and an error explained above would be shown.&lt;/p&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Check onlyoffice Existing in ALFRESCO SHARE&lt;br&gt;In the DOCUMENT-LIBRARY of alfresco share we can see the new addition of ONLY OFFICE FEATURESIn the alfresco document library page we can see the new create features added&lt;br&gt;Also on a file we can see the new features of opening or create using ONLYOFFICE&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/onlyoffice-doclib.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/onlyoffice-doclib.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If we decided to open it in onlyoffice we can see the webview like show below&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/webview.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;INSTALLING DOCUMENT SERVER&lt;br&gt;Notice none of the above feature works without a running instance of a document server.&lt;br&gt;In any OS or installation environment the installation and configuration ONLY has no much difference.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From the &lt;a href=&quot;https://www.onlyoffice.com/download-docs.aspx?from=officeforalfresco#docs-community&quot;&gt;OFFICIAL WEBSITE&lt;/a&gt; there are several options to get only office server running.&lt;br&gt;In our case we would be using the &lt;a href=&quot;https://helpcenter.onlyoffice.com/installation/docs-community-install-docker-arm64.aspx?_ga=2.227019805.1228876411.1673223521-1074737998.1672112363&quot;&gt;DOCKER community version&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;NOTE: INSTALLATION WITHOUT SSL&lt;/p&gt;
&lt;p&gt;As mentioned above we would be installing document server without SSL on a docker instance. But we need to ensure that our DOCKER is using the LOCAL COMPUTER DNS.&lt;/p&gt;
&lt;p&gt;if the docker daemon.json is not configured directly we can still use the dns configuration in or command.&lt;/p&gt;
&lt;p&gt;on my local pc I have the dns set as&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/local-computer-dns.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Well if my dns is set locally and then i can run the docker command to get my container running&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo docker run -dit -p 8080:80   -e JWT_ENABLED=&amp;#39;true&amp;#39; -e JWT_SECRET=&amp;#39;secret&amp;#39; --dns=8.8.8.8 --restart=always \
    -v /volume/onlyoffice/DocumentServer/logs:/var/log/onlyoffice  \
    -v /volume/onlyoffice/DocumentServer/data:/var/www/onlyoffice/Data  \
    -v /volume/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice \
    -v /volume/onlyoffice/DocumentServer/db:/var/lib/postgresql --name documentserver onlyoffice/documentserver&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This command is to ensure I have JWT enabled with the secret key and also just keeping the Google IPV4 default DNS.&lt;br&gt;Also, ensuring the volumes are created for our instance&lt;/p&gt;
&lt;p&gt;Well obviously, if our instance is running we can access the &lt;a href=&quot;http://localhost:8080/welcome/&quot;&gt;server welcome page&lt;/a&gt; .&lt;br&gt;Also, if we enabled the example page we can see the example page for testing our server.&lt;/p&gt;
&lt;h3&gt;Important configuration for JWT TOKEN&lt;/h3&gt;
&lt;p&gt;When our instance is running and we can see the example page or the main page, we still need to check what the default secret is.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;token: &amp;quot;secret&amp;quot;&lt;br&gt;Is what we used in our case. we need to check if that is correctly SET. If not then we set it to any secret we want.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;We need to get into the instance and make some changes on the running services&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Get into the bash&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;sudo docker exec -it {containerID} bash&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/container%20Home.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;We want to get to where our app is installed /etc/--- for installed apps.&lt;/p&gt;
&lt;p&gt;If we open the default.json configuration we can see the default secret keys and token ENABLED for JWT authentication.&lt;br&gt;If any of this configuration is wrong then we get ERRORs in DOCUMENTS SERVER USAGE.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/default.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Also we can see the configuration for local.json file.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/local.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;It is STATED that default changes in default.json are overridden by the configuration in the local.json folder&lt;/p&gt;
&lt;p&gt;--&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/base-commands.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;--&lt;br&gt;If changes was made for the local.json or default.json in documentserver or documentserver-example and saved.&lt;br&gt;Then we need to restart the services&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Fas96/T-images-repo/blob/main/service-restart.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;If the DOCKER_Instance is running properly and we connect to our local computer on the port specified in docker then we can use the example app and test if its working.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ifconfig|grep inet&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and use the ip on port 8080 as specified to access the document server and also you can test the example.&lt;/p&gt;</description>
      <category>DevOps</category>
      <category>Alfresco</category>
      <category>Configuration</category>
      <category>DNS</category>
      <category>docker</category>
      <category>docuent</category>
      <category>Linux</category>
      <category>onlyoffice</category>
      <category>opensource</category>
      <category>server</category>
      <category>services</category>
      <author>Spring Datafication</author>
      <guid isPermaLink="true">https://codefast.tistory.com/38</guid>
      <comments>https://codefast.tistory.com/38#entry38comment</comments>
      <pubDate>Mon, 9 Jan 2023 11:19:04 +0900</pubDate>
    </item>
  </channel>
</rss>