{"data":{"allMarkdownRemark":{"edges":[{"node":{"id":"f3a0fb4b-eb2f-5624-a408-d63e3cee5184","frontmatter":{"category":"Coding","title":"Spring batch integration","date":"2020-02-07","summary":"Usage cases for spring-batch.","thumbnail":null,"authorName":"Artur Yolchyan","authorDescription":"Artur is a Senior Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/spring-batch-integration/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsSAAALEgHS3X78AAAEfElEQVQ4yz2O2VMbBQDGlzJQSylXIEc3F0eODYGEJAQI5GBzbK49kt0cm703CSRQqfQCB9taap1qgY61VXqoPZxxbKe2dWo7tY6d0RdHX/0HfPLRF991qTPO/OZ7+33fB+RDFjruKMWhcgwqwnYqaiVhKwXbiolRgZiuVxJ1LrsgEg25sFilFqrFBblQFXNVgajyBMCkxiuIs4yMMoiDSTiwoC3kc/hdVpdVPzFqRua9MpupS7mqmK9LVF0u1CVFzssCIXMYwKZcTGpMyWLUOe2yjoxAQyNO1YCutbV9f1tbe1u7dcRY47GaMiXuVVSFvMTjModLLApwaRefHqeibqNm4EBnb/+A1mo2T9kHcZ9tGR5LQocPvdFmNusEOqv8lPicxBESi4kstifzabeMuj1Wnba7i/Q71vDgJ/Xc4zXhyWrxq1pyG/eWvEMd+9umfWMLAiFWshKD/g8goROV5LjdBJa9ls9r2edr4svTjRenG8836o9WK7e46EXM5zbpNGoVX0qKdEqk00qFgkBnAGrOko+Nz1jA94iZhyvFZ8fZ707JLzaWft48/vJ08/6b5Y+K4azHph5QlbCIXE7yJYRXco8U4Ffvn7ZoAiPgRSp8vU59s9Z89s7RJ2fXtxerbxGpo5nIOWxaCLr1BhOZDUqlOF+ICyVEQSwnAcuBFmtHi8ekRT0OMjBZQyI3lvgduVCLzvGx0HJi9nw+WPTbJ4dNdSLMUTBXiAnF+GsSgKN7n62zxWnQVAIuOjCxEJnaxuevleMfkMjJzPxGcuZTPs4FoA0U3uHIIhHkqKgCr1CIAx6wBeptTY3ZTiRnzmPhbTp9gyFuc+hNBnm6Kj48tXy1Ri7Brs8WxTMVvITN8fkIT8I8GRXIKFCAR11g1wSo3WSIb9dXbojEnUb1C5m5XkJ+ePvI4/WVHSm3BE98SKNCZpbBg6xyntzz92QxN+U39XYBQDMdfbTWvCpiF/Kpyyy1Wy/fapS+XC5tcclq0JGdMOViHhYP/Sdzyn5+HuBR3+xwXwcABG1DNxvkOgqfLxR3q4vvoujFQvzeSuGymKV8w5C+m4p7GTTIYEE2F+b2iABcZnLW2tsNAPrOg5f4zJVyYgfH7vHibY76epm8eyR/BpuU0inPNBFwW6RcSPGVfQYPcbl5gM14Ex69/gDQvW8f7rHuyujtGnm3yT84Id45Sp8lw0dwZHPrqX0s3N/Xnwl56UyAI0KvCQN02lOIOcfV7erWFvBgOwwZj+VSm0LleDlfR+aOsfSDV3+yS1udHV2aAZNaBQ4aByddTjQ6VcGCAJv1wX472K9S96gOHeyZmkHoWJiJ+Jsxz9ax1Ve//33p3k86tVmnM2s0JgWtdlCrHdKDw5AVAoio+7DW2NOj6+lRazQj71/99crayY8b+P3rd3/5459Hv/017o7otENGo82gt5jNo0rq9cMGg0UPWoBZj7O3Dxzo1/f1alyT6OL645Xm2cvXflw+93Rz93tx6YJaZRocHDMYIKMRAg9bQHDYZIIMBrvZ7PwXcPlkRtKKCQsAAAAASUVORK5CYII=","width":50,"height":50,"src":"/static/dc9516b9327e627890a1f5c7f84c004a/45876/avatar.png","srcSet":"/static/dc9516b9327e627890a1f5c7f84c004a/45876/avatar.png 1x,\n/static/dc9516b9327e627890a1f5c7f84c004a/eb85b/avatar.png 1.5x,\n/static/dc9516b9327e627890a1f5c7f84c004a/4f71c/avatar.png 2x,\n/static/dc9516b9327e627890a1f5c7f84c004a/9ec3e/avatar.png 3x"}}},"headerImage":null},"html":"<p><strong>Intro</strong></p>\n<p>In this article, we will take a look at spring-batch and how it could be used. We will walk through various configurations and we will create an application which reads from a CSV file &#x26; writes into a database with outstanding performance.</p>\n<p>I used the following: Java 11, Spring 5+, Spring Boot 2 and Maven-based project.</p>\n<p><strong>Create a Project</strong></p>\n<p>First, we need to create a Spring Boot 2 project. We recommend that you do so by visiting <a href=\"https://start.spring.io/\">spring initializer</a>, which is a useful tool to generate spring projects with required dependencies and configurations.</p>\n<p><strong>Dependencies</strong></p>\n<p>We need the dependencies below to run and test the project:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">&lt;dependency> \n &lt;groupId>org.springframework.boot&lt;/groupId>\n &lt;artifactId>spring-boot-starter&lt;/artifactId>\n&lt;/dependency>\n   \n&lt;dependency>\n &lt;groupId>org.springframework.boot&lt;/groupId>\n &lt;artifactId>spring-boot-starter-test&lt;/artifactId>\n &lt;scope>test&lt;/scope>\n &lt;exclusions>\n    &lt;exclusion>\n     &lt;groupId>org.junit.vintage&lt;/groupId>\n      &lt;artifactId>junit-vintage-engine&lt;/artifactId>\n    &lt;/exclusion>\n &lt;/exclusions>\n&lt;/dependency>\n\n&lt;dependency>\n &lt;groupId>org.springframework.boot&lt;/groupId>\n &lt;artifactId>spring-boot-starter-batch&lt;/artifactId>\n&lt;/dependency>\n\n&lt;dependency>\n &lt;groupId>org.springframework.boot&lt;/groupId>\n &lt;artifactId>spring-boot-starter-data-jpa&lt;/artifactId>\n&lt;/dependency>    \n\n&lt;dependency>\n &lt;groupId>org.projectlombok&lt;/groupId>\n &lt;artifactId>lombok&lt;/artifactId>\n &lt;version>1.18.10&lt;/version>\n &lt;scope>provided&lt;/scope>\n&lt;/dependency>\n\n&lt;dependency>\n &lt;groupId>com.h2database&lt;/groupId>\n &lt;artifactId>h2&lt;/artifactId>\n&lt;/dependency>\n    \n&lt;dependency>\n &lt;groupId>org.springframework.boot&lt;/groupId>\n &lt;artifactId>spring-boot-starter-test&lt;/artifactId>\n &lt;scope>test&lt;/scope>\n &lt;exclusions>\n     &lt;exclusion>\n     &lt;groupId>org.junit.vintage&lt;/groupId>\n     &lt;artifactId>junit-vintage-engine&lt;/artifactId>\n     &lt;/exclusion>\n &lt;/exclusions>\n&lt;/dependency>\n\n&lt;dependency>\n &lt;groupId>org.springframework.batch&lt;/groupId>\n &lt;artifactId>spring-batch-test&lt;/artifactId>\n &lt;scope>test&lt;/scope>\n&lt;/dependency>\n\n&lt;dependency>\n &lt;groupId>org.hamcrest&lt;/groupId>\n &lt;artifactId>hamcrest-all&lt;/artifactId>\n &lt;version>1.3&lt;/version>\n &lt;scope>test&lt;/scope>\n&lt;/dependency></code></pre></div>\n<p><em>spring-boot-starter-batch</em> dependency includes all the configurations to run the spring batch application. <a href=\"https://projectlombok.org/\">Lombok</a>  is just a helper dependency to write the code faster and cleaner. <a href=\"http://www.h2database.com/\">H2</a>  is used as an in-memory database. <em>spring-boot-starter-test</em> and <em>spring-batch-test</em> are included for test purposes.</p>\n<p><strong>Book Class</strong></p>\n<p>Let’s create a model class book, which will represent a book. This will just serve as a model class and will help us during implementation of spring batch.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Data\n\npublic class Book {\nprivate String title;\nprivate String description;\nprivate String author;\n}</code></pre></div>\n<p><strong>Configuration</strong></p>\n<p>Let’s create a class called SpringBatchConfiguration. We will add all required configurations here. First, let’s annotate this class with <a href=\"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html\">@Configuration</a> to be able to inject beans, and with <a href=\"https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.html\">@EnableBatchProcessing</a> to enable spring batch processing. Additionally, we can add <a href=\"https://projectlombok.org/features/constructor\">@RequiredArgsConstructor</a> from Lombok which would help us to generate constructor with parameters. These parameters are the ones which are marked as final class properties. These properties will be injected as spring beans. Our class will be like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Configuration\n@EnableBatchProcessing\n@RequiredArgsConstructor\npublic class SpringBatchConfiguration</code></pre></div>\n<p>Now, in SpringBatchConfiguration class let’s add properties which need to be injected into the constructor:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">private final JobBuilderFactory jobBuilderFactory;\nprivate final StepBuilderFactory stepBuilderFactory;</code></pre></div>\n<p><em>jobBuilderFactory</em> and <em>stepBuilderFactory</em> are declared in spring batch jar as spring beans so that we can inject them in any class we want.</p>\n<p><strong>File Reader</strong></p>\n<p>Now, we need to declare and initialize spring beans to configure the batch process. The first bean which we will need will be responsible for reading from a file line by line. Spring Batch provides a default class for it. The class name is <em>FlatFileItemReader</em>. Similarly, spring has different default reader classes for reading from a relational database, mongodb and etc. However, if you need, you can create your own reader and implement it in a way you want.</p>\n<p>Let’s now see what <em>FlatFileItemReader</em> injection will look like.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Bean\n@StepScope\npublic FlatFileItemReader&lt;Book> bookReader(@Value(\"#{jobParameters['filePath']}\") final String filePath\n) {\nreturn new FlatFileItemReaderBuilder&lt;Book>()\n    .name(\"personItemReader\")\n    .resource(new ClassPathResource(filePath))\n    .delimited()\n    .names(new String[]{\"title\", \"description\", \"author\"})\n    .fieldSetMapper(new BeanWrapperFieldSetMapper&lt;Book>() {{\n    setTargetType(Book.class);\n    }})\n    .build();\n}</code></pre></div>\n<p>We are configuring that the bean reader should read data from the given file path, which should be a CSV file having rows with title, description and author respectively.</p>\n<p>The <a href=\"https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/core/scope/StepScope.html\">StepScope</a> means to initialize this bean after each step, so file path could be dynamically set when the spring batch job is launched. We will come to that later, how to pass the file path later in this article.</p>\n<p><strong>Item Writer</strong></p>\n<p>Now, let’s create a writer class, which will take the data and write into the relational database.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Bean\npublic JdbcBatchItemWriter&lt;Book> writer(final DataSource dataSource) {\n    return new JdbcBatchItemWriterBuilder&lt;Book>()\n        .itemPreparedStatementSetter((book, preparedStatement) -> {\n            preparedStatement.setString(1, book.getTitle());\n            preparedStatement.setString(2, book.getDescription());\n            preparedStatement.setString(3, book.getAuthor());\n        })\n        .sql(\"INSERT INTO books (title, description, author) VALUES (title, description, author_surname)\")\n        .dataSource(dataSource)\n        .build();\n} </code></pre></div>\n<p>In the writer bean, we are setting item processors and adding values inside <em>preparedStatement</em> accordingly, which book property should be inserted for each db table column.  </p>\n<p><strong>Step Configuration</strong></p>\n<p>Now, let’s configure a step which will be executed in the batch process. In our case, the configuration will look like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Bean\npublic Step step1(final ItemWriter&lt;Book> writer, final ItemReader&lt;Book> reader) {\n    return stepBuilderFactory.get(\"step1\")\n        .&lt;Book, Book> chunk(100)\n        .reader(reader)\n        .processor((ItemProcessor&lt;Book, Book>) book -> book)\n        .writer(writer)\n        .build();\n}</code></pre></div>\n<p>In our scenario, we have only one step, but it's also possible to configure multiple steps. Here, we are creating a spring batch step with the name <em>step1</em> and setting reader and writer accordingly. These are the readers and writers which we created as spring beans earlier.</p>\n<p>We are setting chunk as 100, which means the items chunk proceeded is 100. We can make this configurable too. The processor is for converting the current object to the one which the writer should proceed with. In our case, it is the same object.</p>\n<p><strong>Job Configuration</strong></p>\n<p>Last but not least, let’s configure the job which should be executed.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Bean\npublic Job importUserJob(final Step step1) {\n    return jobBuilderFactory.get(\"bookReaderJob\")\n        .incrementer(new RunIdIncrementer())\n        .flow(step1)\n        .end()\n        .build();\n}</code></pre></div>\n<p>Here, we create a job with the name <em>bookReaderJob</em>. We add an incrementer <a href=\"https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/core/launch/support/RunIdIncrementer.html\">RunIdIncrementer</a>, which is an id generator for the tables which are specifically designed to store the details about job executions in the database. After each time the spring batch job is executed, it will save details about the execution. To check the schema structure for storing this data, take a look at <a href=\"https://github.com/spring-projects/spring-batch/blob/master/spring-batch-core/src/main/resources/org/springframework/batch/core/schema-mysql.sql\">this sql</a>. It is for MySql, but other SQL scripts are available too.</p>\n<p>Additionally, we add flow by which the job should be executed. Currently, we have only one step in our flow, so we add it.  </p>\n<p>Please also add this config: <code class=\"language-text\">spring.batch.job.enabled=false</code> in your properties config file so that spring batch job won’t be executed automatically with no parameters when the application is started.</p>\n<p><strong>Execution</strong></p>\n<p>To execute the job, we need to declare <a href=\"https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/core/launch/JobLauncher.html\">JobLauncher</a> and launch the job. To do so, we need to create the below class:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Component\n@RequiredArgsConstructor\npublic class SpringBatchExecutor {  \n    private final JobLauncher jobLauncher;\n    private final Job job;  \n\n    @SneakyThrows\n    public void execute(final String filePath) {\n        JobParameters parameters = new JobParametersBuilder()\n            .addString(\"filePath\", filePath)\n            .toJobParameters();  \n        jobLauncher.run(job, parameters);\n    }  \n}</code></pre></div>\n<p>Now, we can call the execute method from whenever we want, with the file path from which the data should be read.</p>\n<p><strong>Additional Classes</strong></p>\n<p>There are a few additional classes which you will need to execute your code.</p>\n<p>Create a class <em>BookEntity</em> so that spring data JPA will automatically create the book table for you. Then you can create repository.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Data\n@Entity\n@Table(name = \"books\")\npublic class BookEntity {\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n    private String title;\n    private String description;\n    private String authorFullName;\n}</code></pre></div>\n<p>Then create the interface <em>BookRepository</em> and extend it from <em>JpaRepository</em>. At the moment, we will need this only for testing.  </p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Repository\npublic interface BookRepository extends JpaRepository&lt;BookEntity, Long> {\n} </code></pre></div>\n<p><strong>Testing</strong></p>\n<p>No one likes a code which is not tested. So, let’s write a few test cases for our class.</p>\n<p>Here is a code sample for test cases:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Slf4j\n\n@SpringBootTest\nclass SpringBatchSampleApplicationIntegrationTest {\n\n    @Autowired\n    private SpringBatchExecutor springBatchExecutor;\n    \n    @Autowired\n    private BookRepository bookRepository;\n\n    @Test\n    public void testExecution() {\n        long initialCount = bookRepository.count();\n        assertThat(initialCount, equalTo(0L));\n        springBatchExecutor.execute(\"sample-data.csv\");\n        long count = bookRepository.count();\n        assertThat(count, equalTo(7L));\n    } \n\n    @Test\n    public void testLargeData() {\n        long startTime = System.currentTimeMillis();\n        long initialCount = bookRepository.count();\n        assertThat(initialCount, equalTo(0L));\n        springBatchExecutor.execute(\"large-data.csv\");\n        long count = bookRepository.count();\n        assertThat(count, equalTo(60000L));\n        long endTime = System.currentTimeMillis();\n        log.info(\"executed in miles: {}\", endTime - startTime);\n    }\n}</code></pre></div>\n<p>The second test executes in ≈ <strong>3500 ms</strong> in a machine with a 2.2 Ghz Intel Core i7 and 16GB ram. It proceeds 60K lines of CSV file, and saves it into a relational database.</p>\n<p>You can check out the working sample code in <a href=\"https://github.com/yolch-yolchyan/spring-batch-sample\">github</a>,</p>","fields":{"slug":"/spring-batch-integration/","tags":["auto1","engineering","spring","code","java"]}}},{"node":{"id":"a3a21c38-873e-56db-a170-eec0e6136040","frontmatter":{"category":"Coding","title":"Writing IntelliJ plugins","date":"2019-12-10","summary":"How to write a simple IntelliJ plugin","thumbnail":{"relativePath":"pages/intellij-plugin/logo.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAAEyElEQVQ4y3WVe0xTVxzHz723rfZBsVeqnc4Yw0aYFSiFFZlZxnSo4w+gSBWEglTmA59jCt4WCOUxq+J4zGwaMqfJfDBi2GbMxjJfMXMzJks0Y5ngfE0mqAwrFLHtPb+de4CKf+wkv5zfOed3Pr/vOb+Te9FAzEokNV9cLvq/Nmpew8L8DIQOANJUPEdh+wGpBB8jrSldo0hd7n0RLJry0fA4bCg2RxYw5S3zm/ISnsWt1vvi8qZMxD1KLkVvb+lmJifS7hrmpJ4lCfidAy8WAqZ8dqzPSwFzIQRN+UEy95SMbxK7MhK3umQiVlnuLVQKwxcVW//SS2O94JNFFZyja3NLHyD03JSHIN5OMxHQZ5C4Fgg0CAlFAIkOAMs6gIWbiV9sQ0cgTlMl+tW7ATSV+E64y2+R9kWVDXJR226PZZSAUvPG5mpxvP0+MfjjjfTg9eh0/Nv8TPGXBdmBS3H5cC52tS8253SffNMN0BZfHdVu7AK+tC9gIIon1MdsvkXvkKojd2aT1N02ZgXDWBnmGBbLJWM5IL4oZzhQEEOMTESsHBBiAjNzz8BrVSJEb721b3taOzdWlIQien+kECfB8gHciM8NkCHOyLLC711d+MPSUkzGIM159njE5IVJ1CfVgXnZbeKbpQ9Ey84+iCy7kxUqylB8QeQoUTeatAWumteIMhKs43m42dMDFotFAgDDMHD+/HlIT88YA7IsNmUcwWmbb4hRu+4BX9mfGQI+SSiY/SBxneeflJLHZ5NKQM7IqKofOzth1qxZMK4QOjo6CDCd+izLwNLlLXhh+R2sr3oEM4SHy8bUOYz07H0daFrQNWPw57XJQG8iIQEwxmC1WiE1NRWampqgu7sbzGYzBUqniLV9gee4B3GE6zHonAMpFAh7ZPSx+sqmH4Pa6XB5++vSHcJbixbhpsZGSEtLA6PRCK2trZCTkxNSK5m+oB2/4h6WYDjcOZgcOvLDHbxyZJfuT6ifDhc3zA8qZIqXNr5sTMiPsJ/CevcoEFgwzPnETGHPBB1VeG+TwQDV2rNnC98FBmlEhUKG1So1TJ06FeRyOchkMuA47iWgzv4t5msCQGB+ldNrDCns3b6AQgGOs42LS67PnR0J+z9pCDY3N+ODhw7i9RvW08qOW8jX2k/jaTUY1M6nI0rhaSSF9e2IRlXvXKD+paJrEbVL9varp6hBGx7m53lejNDxYrhKE6TKGAYj8tiJT4Ea+5mA1o1B5Rz2KwXvnJDClszDtNKfWw9bW7KOwrYl9bAltQGKF3sgb/k+WJpzAGIcXwYiHV/j2Y7vxAjHD4FwxznQurygqQdQunw9yrIBLYV5rEdRQ/YJCty74qujhwp/gt253/R/bP/+eJPj8vvr3JdWvld95X6Spxeiq//Gc2uegMEDoHP7Iaxy5ILKOVREjjtN2k+UIlS34hgF12UeVtRln/i02ta2aWN6q37ydy9mfQdvFK61zqu4CwZnbx8v9Ddrd95PnBxDVI455dknaE9A7OSA+lWn2Orsdi7zo05uYu5V513LTKHXMDHW12Gkcvk4pTBEi6qegLptJ2nfU9CJam1tXKWtjRFWtSND1S06b3H+yiRWXg8l1Ff8y5G3x6oELyJK0cwa6TfwmK79B0KrRX19cxThAAAAAElFTkSuQmCC","width":325,"height":325,"src":"/static/b2f976ed5fa752977d8f8f9b2516534c/b3029/logo.png","srcSet":"/static/b2f976ed5fa752977d8f8f9b2516534c/b3029/logo.png 1x,\n/static/b2f976ed5fa752977d8f8f9b2516534c/8d141/logo.png 1.5x,\n/static/b2f976ed5fa752977d8f8f9b2516534c/ee72c/logo.png 2x,\n/static/b2f976ed5fa752977d8f8f9b2516534c/5dfa8/logo.png 3x"}}},"authorName":"Piotr Czekaj","authorDescription":"Piotr is a Senior Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/intellij-plugin/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/intellij-plugin/header.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsSAAALEgHS3X78AAADGklEQVQozx3R60/bVRjA8V80m2N4IVkWcfpmqyulTdd7oRYopEDbyaXlVgptobANkAzrUpwbyjZvgMpQ7CxhGCaXUTcv04mRRYMkKpB1MLYpIKkymb5S/4WvZ7745DkvnnOey5FS87qQWbqY0zWyIEzrmxkxHOFHcXZkRZCsZ0ixnmKH9TQPWV7m0eIo22q/JmjvI6ENsijyh7I62G7rYXt2F1KgpIo2TZhlbYBFkTCjDaE2Rdhn6mS36TiPC+nml9ilP0a6rQ91wxwZhxJ4ar9kMbuDdeMR+h0DyAOzyBwxpJDhMCsHAlzXBFgQ7mj8DGqaeUr3Agrt8yh0YWQiZolOq9wTuLxXcFZ/SmHNFVrKL/DKwXMcrPkcu2+aYkGKqkKsquu5rvZzQ7gf19R1nFTUo1M0Y5E3YNWGidu6mSzsQdc0j+ZwgrzgLFUVcWEKn/uiMInfPY40pPKxrvWypPFyU7ilqWZJX8dr9l4UrjFUzlFy3OJS8BqWtmVkRzeQtf/K3qNJCsT4EWeUU65+ely9HHOdQ3pR4Wa1OI8Vez637DaWiwp5tfxtIidmGbywxsilJH2xn3lneI3RyXU+iK3Q1votPu9VfP5vOOGMEbeHmXEcoregV+wwvYx4volk816SoSeZrS3lfPmbfFj2OqPeQcbqo4z7+pnwDvBxYJjJ2iFGSt8j5jhLzPUuY7ndXLREmMruZMJyHCmyq4jO3UWMGg1MO+XM5z7LkiHEDwcamVM28JM6wFpODas5Xm7omljRt3DH1Mptcxu/GFv4yNlNZ3CQPk8P14ytSG+l5XHmESund+ZzcmcuX+xx8ldmNckMD78pKthUevjHXMK/5lLuZlYIlWwpq9lSVJJUeQkFL2N77ntsHfO8URpFGk41M572DLFUI++nGDj/sJnb+0q4l1nFH8LW/yrZ2O8mKfdwVxT5/X4x4c8MN+3ip1XtGxj8X+GouYw081gW9+TlfJaiY/xBJWMPKPlkh5bEEwXc3GMnkV7Ad2nZxLepuZpqYHN/GVvisU3h76dLmDKGsTQuoK+7RJNrgP8AU8rtTZmilCkAAAAASUVORK5CYII=","width":1280,"height":720,"src":"/static/6fae10ea7503a11a8f308ac2e2a5217a/26421/header.png","srcSet":"/static/6fae10ea7503a11a8f308ac2e2a5217a/26421/header.png 1x"}}}},"html":"<h2>Background</h2>\n<p>During analysis of why some services take a long time to build, several problems have been found, mostly related to number of Spring contexts that were created during integration tests. More about those problems can be found in <a href=\"https://auto1.tech/integration-test-speedup\">previous blog post</a>. In order to decrease the likelihood that slow tests will appear at AUTO1, we implemented an IntelliJ plugin which warns a developer about possible problems when he writes code and provides quick fixes if they are applicable.</p>\n<h2>Plugin inspections</h2>\n<ul>\n<li>warns about usage of <code class=\"language-text\">@DirtiesContext</code> annotation which slows tests down because it forces creation of new Spring context</li>\n<li>warns about specifying the same list of profiles but in different order in <code class=\"language-text\">@ActiveProfiles</code> (slows tests down because different Spring context would have to be created for each combination)</li>\n<li>warns if number of distinct profile combinations used in <code class=\"language-text\">@ActiveProfiles</code> is greater than 3</li>\n<li>warns if it finds <code class=\"language-text\">@FeignClient</code> (or DTO used by client) not documented with Swagger annotations</li>\n<li>warns if remote HTTP call is used inside method annotated with <code class=\"language-text\">@Transactional</code></li>\n</ul>\n<p>During the plugin development, we realized that resources on writing IntelliJ plugins are scarce, and therefore decided to create a step by step tutorial on how to implement <code class=\"language-text\">@DirtiesContext</code> inspection.</p>\n<h2>Create plugin</h2>\n<p>In our tutorial we will be using the community edition of IntelliJ 2018.3.5. Final source code is available on <a href=\"https://github.com/pczekaj/tutorial-intellij-plugin\">github</a>.\nThere are several ways on how to create IntelliJ plugin. The recommended one is to use Intellij plugin for Gradle and that’s what we will use in this tutorial. Let’s start with creating new project using <em>File > New > Project...</em>, select Gradle and make sure that in <em>Additional Libraries and Frameworks</em> both <em>Java</em> and <em>Intellij Platform Plugin</em> are selected.\nIf you cannot see “Gradle” or “Intellij Platform Plugin” then please make sure that both “Gradle” and “Plugin DevKit” IntelliJ plugins are installed.\nContinue next steps of the wizard using default values, use any groupId and artifactId. After some time IntelliJ will download dependencies and create an empty plugin.</p>\n<h2>Inspection</h2>\n<p>Our inspection should warn a developer each time there is a class annotated with <code class=\"language-text\">org.springframework.test.annotation.DirtiesContext</code> and provide quick fix which deletes <code class=\"language-text\">@DirtiesContext</code>. If Spring is not your thing then any other annotation can be used instead.</p>\n<p>There are two kinds of inspections:</p>\n<p>Local inspections are executed in the background when file is opened, in general they have access to currently open file. Local inspection cannot report problem for not currently processed file. Inspection class has to extend <code class=\"language-text\">com.intellij.codeInspection.LocalInspectionTool</code> or one of subclasses.\nGlobal inspections work only in batch mode when analysis is manually triggered via <em>Analyze > Inspect Code</em> and see complete graph of references between classes and can report problem for any file. Inspection class has to extend <code class=\"language-text\">com.intellij.codeInspection.GlobalInspectionTool</code> or one of subclasses.</p>\n<p>We don’t need to access complete graph of references and we would like to give a hint that something is wrong as soon as possible so local inspection is a better choice for our use case. First problem that we encounter is to pick proper base class. One approach is to ask IntelliJ to show class Hierarchy of <code class=\"language-text\">LocalInspectionTool</code> and take a look what other inspections are extending. In this case <code class=\"language-text\">AbstractBaseJavaLocalInspectionTool</code> seems to be a good choice since most of Java inspections are based on it.</p>\n<p>Create new class named <code class=\"language-text\">DirtiesContextInspection</code> with following content:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">DirtiesContextFirstVersionInspection</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">AbstractBaseJavaLocalInspectionTool</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">String</span> DIRTIES_CONTEXT <span class=\"token operator\">=</span> <span class=\"token string\">\"org.springframework.test.annotation.DirtiesContext\"</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">String</span> DESCRIPTION_TEMPLATE <span class=\"token operator\">=</span> <span class=\"token string\">\"Usage of @DirtiesContext makes integration tests slower\"</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getDisplayName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string\">\"Usage of @DirtiesContext is not recommended\"</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getGroupDisplayName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token class-name\">GroupNames</span><span class=\"token punctuation\">.</span>PERFORMANCE_GROUP_NAME<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getShortName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string\">\"DirtiesContext\"</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token keyword\">boolean</span> <span class=\"token function\">isEnabledByDefault</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token class-name\">PsiElementVisitor</span> <span class=\"token function\">buildVisitor</span><span class=\"token punctuation\">(</span><span class=\"token annotation punctuation\">@NotNull</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">ProblemsHolder</span> holder<span class=\"token punctuation\">,</span> \n                                          <span class=\"token keyword\">boolean</span> isOnTheFly<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">JavaElementVisitor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n\n            <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">visitAnnotation</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">PsiAnnotation</span> annotation<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">super</span><span class=\"token punctuation\">.</span><span class=\"token function\">visitAnnotation</span><span class=\"token punctuation\">(</span>annotation<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n                <span class=\"token class-name\">String</span> qualifiedName <span class=\"token operator\">=</span> annotation<span class=\"token punctuation\">.</span><span class=\"token function\">getQualifiedName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n                <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>DIRTIES_CONTEXT<span class=\"token punctuation\">.</span><span class=\"token function\">equals</span><span class=\"token punctuation\">(</span>qualifiedName<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                    holder<span class=\"token punctuation\">.</span><span class=\"token function\">registerProblem</span><span class=\"token punctuation\">(</span>annotation<span class=\"token punctuation\">,</span> DESCRIPTION_TEMPLATE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n                <span class=\"token punctuation\">}</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>The most interesting thing happens in a visitor which is notified each time a Java annotation is encountered in source code. By overriding different methods, plugin can process methods, classes, imports etc. In our case we check if fully qualified name of annotation matches our expectations and register a problem when that’s the case. Later on we will change this class to include also a quick fix. Creation of inspection class is not enough to make it available in IntelliJ - it’s also needed to register inspection in <code class=\"language-text\">plugin.xml</code> which among other things describes what plugin does, what other plugins are required and in which version of IntelliJ it can be used.</p>\n<p>It’s possible to register each inspection one by one in <code class=\"language-text\">plugin.xml</code> under extensions tag and configure inspection using xml but we find it easier to register <code class=\"language-text\">inspectionToolProvider</code> and configure using it in Java code.</p>\n<p>Create the following class to implement our inspection provider:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">CodeInspectionProvider</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">InspectionToolProvider</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">public</span> <span class=\"token class-name\">Class</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token function\">getInspectionClasses</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Class</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">{</span>\n                <span class=\"token class-name\">DirtiesContextInspection</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">class</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And register it in <code class=\"language-text\">plugin.xml</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\">   <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>extensions</span> <span class=\"token attr-name\">defaultExtensionNs</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>com.intellij<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>inspectionToolProvider</span> <span class=\"token attr-name\">implementation</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>com.auto1.intellij.tutorial.CodeInspectionProvider<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">/></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>extensions</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>Now it’s time to check our inspection in action by running runIde gradle task. This could be done from terminal by executing <code class=\"language-text\">./gradlew runIde</code> but it’s better to use Gradle view in IntelliJ since it allows to start IDE in debug mode (if needed just right click on task and select Debug, you can create run configuration to speed-up in the future). New IntelliJ instance should show up, if you already have sources of some project that uses Spring Boot then open it, otherwise you could create a new project. Annotate some class with <code class=\"language-text\">@DirtiesContext</code> annotation and observe inspection marker showing up. In case of problems logs can be found at <code class=\"language-text\">build/idea-sandbox/system/log/</code>.</p>\n<h2>Adding quick fix</h2>\n<p>Many inspections report not only problems but also provide automatic ways of fixing issues. In case of DirtiesContext, it’s not possible to provide safe way of removing it because DirtiesContext is often used when bean holds some state which makes tests dependent on each other. Usually we want to remove the annotation and then figure out the \"dirty parts\" and clean them up in an elegant way. Since the second part is hard to automate we will provide quick fix which only removes annotation.</p>\n<p>Go back to <code class=\"language-text\">DirtiesContextInspection</code> class and add quick fix:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">   <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">DeleteQuickFix</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">LocalQuickFix</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">public</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">return</span> <span class=\"token string\">\"Removes usage of @DirtiesContext\"</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token keyword\">public</span> <span class=\"token keyword\">void</span> <span class=\"token function\">applyFix</span><span class=\"token punctuation\">(</span><span class=\"token annotation punctuation\">@NotNull</span> <span class=\"token class-name\">Project</span> project<span class=\"token punctuation\">,</span> <span class=\"token annotation punctuation\">@NotNull</span> <span class=\"token class-name\">ProblemDescriptor</span> descriptor<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            descriptor<span class=\"token punctuation\">.</span><span class=\"token function\">getPsiElement</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">delete</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n\n        <span class=\"token keyword\">public</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getFamilyName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">return</span> <span class=\"token function\">getName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Next step is to pass quick fix when problem is registered:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">holder<span class=\"token punctuation\">.</span><span class=\"token function\">registerProblem</span><span class=\"token punctuation\">(</span>annotation<span class=\"token punctuation\">,</span> DESCRIPTION_TEMPLATE<span class=\"token punctuation\">,</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">DeleteQuickFix</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Executing <code class=\"language-text\">runIde</code> Gradle task should prove that quick fix works as expected. </p>\n<h2>Internationalization</h2>\n<p>Up to this point we have used hardcoded strings inside inspection name and description. To allow the plugin to be accessible in different languages we can externalize the messages. For this purpose we can use properties file. First create <code class=\"language-text\">PluginBundle</code> class:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">PluginBundle</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token class-name\">Reference</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ResourceBundle</span><span class=\"token punctuation\">></span></span> ourBundle<span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">final</span> <span class=\"token class-name\">String</span> BUNDLE <span class=\"token operator\">=</span> <span class=\"token string\">\"com.auto1.intellij.tutorial.PluginBundle\"</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">private</span> <span class=\"token class-name\">PluginBundle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token class-name\">String</span> <span class=\"token function\">message</span><span class=\"token punctuation\">(</span><span class=\"token annotation punctuation\">@NotNull</span> <span class=\"token annotation punctuation\">@PropertyKey</span><span class=\"token punctuation\">(</span>resourceBundle <span class=\"token operator\">=</span> BUNDLE<span class=\"token punctuation\">)</span> <span class=\"token class-name\">String</span> key<span class=\"token punctuation\">,</span> \n                                 <span class=\"token annotation punctuation\">@NotNull</span> <span class=\"token class-name\">Object</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> params<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token class-name\">CommonBundle</span><span class=\"token punctuation\">.</span><span class=\"token function\">message</span><span class=\"token punctuation\">(</span><span class=\"token function\">getBundle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> key<span class=\"token punctuation\">,</span> params<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">private</span> <span class=\"token keyword\">static</span> <span class=\"token class-name\">ResourceBundle</span> <span class=\"token function\">getBundle</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">ResourceBundle</span> bundle <span class=\"token operator\">=</span> <span class=\"token class-name\"><span class=\"token namespace\">com<span class=\"token punctuation\">.</span>intellij<span class=\"token punctuation\">.</span>reference<span class=\"token punctuation\">.</span></span>SoftReference</span><span class=\"token punctuation\">.</span><span class=\"token function\">dereference</span><span class=\"token punctuation\">(</span>ourBundle<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>bundle <span class=\"token operator\">==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            bundle <span class=\"token operator\">=</span> <span class=\"token class-name\">ResourceBundle</span><span class=\"token punctuation\">.</span><span class=\"token function\">getBundle</span><span class=\"token punctuation\">(</span>BUNDLE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            ourBundle <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">SoftReference</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">(</span>bundle<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">return</span> bundle<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Then create a new file matching <code class=\"language-text\">BUNDLE</code> constant, in my case it will be <code class=\"language-text\">src/main/resources/com/auto1/intellij/tutorial/PluginBundle.properties</code> with content:</p>\n<div class=\"gatsby-highlight\" data-language=\"properties\"><pre class=\"language-properties\"><code class=\"language-properties\"><span class=\"token attr-name\">inspection.dirties.context.display.name</span><span class=\"token punctuation\">=</span><span class=\"token attr-value\">Usage of @DirtiesContext is not recommended</span>\n<span class=\"token attr-name\">inspection.dirties.context.problem.descriptor</span><span class=\"token punctuation\">=</span><span class=\"token attr-value\">Usage of @DirtiesContext makes integration tests slower</span>\n<span class=\"token attr-name\">inspection.dirties.context.use.quickfix</span><span class=\"token punctuation\">=</span><span class=\"token attr-value\">Removes usage of @DirtiesContext</span></code></pre></div>\n<p>Register bundle in <code class=\"language-text\">plugin.xml</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>resource-bundle</span><span class=\"token punctuation\">></span></span>com.auto1.intellij.tutorial.PluginBundle<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>resource-bundle</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>And finally use bundle in inspection, for example:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">    <span class=\"token keyword\">public</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getDisplayName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token class-name\">PluginBundle</span><span class=\"token punctuation\">.</span><span class=\"token function\">message</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"inspection.dirties.context.display.name\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<h2>Testing</h2>\n<p>We picked <code class=\"language-text\">LightPlatformCodeInsightFixtureTestCase</code> as base for our tests because it is recommended in the documentation. Unfortunately, testing appeared harder to set up properly than expected.</p>\n<p>First problem was that our tests couldn’t see classes from JDK, which was fixed by specifying project descriptor to use internal JDK: </p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">    <span class=\"token keyword\">protected</span> <span class=\"token class-name\">LightProjectDescriptor</span> <span class=\"token function\">getProjectDescriptor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">LightProjectDescriptor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">public</span> <span class=\"token class-name\">Sdk</span> <span class=\"token function\">getSdk</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n                <span class=\"token keyword\">return</span> <span class=\"token class-name\">JavaAwareProjectJdkTableImpl</span><span class=\"token punctuation\">.</span><span class=\"token function\">getInstanceEx</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getInternalJdk</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token punctuation\">}</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Second problem was that visitor received incorrect fully qualified class name of the annotation. Instead of <code class=\"language-text\">org.springframework.test.annotation.DirtiesContext</code>, it got <code class=\"language-text\">DirtiesContext</code> while it worked fine for real project in IDE. It turns out that such behaviour occurs when test project doesn’t see definition of some class. This is fixable by either hardcoding problematic class into test or by adding dependency as library to the project. Second approach avoids copying source code from other projects and seems to be more interesting so it will be presented here. In order to download dependency jar we use <code class=\"language-text\">ShrinkWrap</code> library:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token keyword\">private</span> <span class=\"token class-name\">File</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token function\">getMavenArtifacts</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> mavenArtifacts<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">File</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> files <span class=\"token operator\">=</span> <span class=\"token class-name\">Maven</span><span class=\"token punctuation\">.</span><span class=\"token function\">resolver</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n                            <span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span>mavenArtifacts<span class=\"token punctuation\">)</span>\n                            <span class=\"token punctuation\">.</span><span class=\"token function\">withoutTransitivity</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n                            <span class=\"token punctuation\">.</span><span class=\"token function\">asFile</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>files<span class=\"token punctuation\">.</span>length <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n            <span class=\"token keyword\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IllegalArgumentException</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Failed to resolve artifacts \"</span> <span class=\"token operator\">+</span> <span class=\"token class-name\">Arrays</span><span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span>mavenArtifacts<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n        <span class=\"token keyword\">return</span> files<span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<p>When dependency is resolved and downloaded into local Maven cache it can be added as library with code listed below:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">   <span class=\"token keyword\">protected</span> <span class=\"token keyword\">void</span> <span class=\"token function\">attachMavenLibrary</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> mavenArtifact<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token class-name\">File</span><span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> jars <span class=\"token operator\">=</span> <span class=\"token function\">getMavenArtifacts</span><span class=\"token punctuation\">(</span>mavenArtifact<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token class-name\">Arrays</span><span class=\"token punctuation\">.</span><span class=\"token function\">stream</span><span class=\"token punctuation\">(</span>jars<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">forEach</span><span class=\"token punctuation\">(</span>jar <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n            <span class=\"token class-name\">String</span> name <span class=\"token operator\">=</span> jar<span class=\"token punctuation\">.</span><span class=\"token function\">getName</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n            <span class=\"token class-name\">PsiTestUtil</span><span class=\"token punctuation\">.</span><span class=\"token function\">addLibrary</span><span class=\"token punctuation\">(</span>myFixture<span class=\"token punctuation\">.</span><span class=\"token function\">getProjectDisposable</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> myModule<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> jar<span class=\"token punctuation\">.</span><span class=\"token function\">getParent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<p>It’s important to use <code class=\"language-text\">myFixture.getProjectDisposable()</code> instead of <code class=\"language-text\">myFixture.getProject()</code> otherwise there is an exception during test shutdown:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">com.intellij.openapi.util.TraceableDisposable$DisposalException: Virtual pointer 'jar:///somePath/.m2/repository/org/springframework/spring-test/5.1.5.RELEASE/spring-test-5.1.5.RELEASE.jar!/' hasn't been disposed</code></pre></div>\n<p>Next surprise is that by default test searches for test data in strange location inside IntelliJ home folder which can be fixed with overriding <code class=\"language-text\">getTestDataPath</code>. Since input files most likely won’t compile because of missing imports and possible usage of special markers like <em><caret></em> we don’t use <code class=\"language-text\">src/test/java</code> folder to store them:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">    <span class=\"token annotation punctuation\">@Override</span>\n    <span class=\"token keyword\">protected</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getTestDataPath</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token keyword\">return</span> <span class=\"token string\">\"src/test/testData\"</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Inspection tests can be done by providing file to analyse and resulting file that should be created after given quick fix has been applied. Inspection tests use <code class=\"language-text\">configureByFile</code> to load input file, <code class=\"language-text\">doHighlighting</code> to trigger source code analysis, launchAction to execute quick fix and finally <code class=\"language-text\">checkResultByFile</code> to compare results against <em>after</em> file.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\">    myFixture<span class=\"token punctuation\">.</span><span class=\"token function\">configureByFile</span><span class=\"token punctuation\">(</span>testName <span class=\"token operator\">+</span> <span class=\"token string\">\".java\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    myFixture<span class=\"token punctuation\">.</span><span class=\"token function\">enableInspections</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">DirtiesContextInspection</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    myFixture<span class=\"token punctuation\">.</span><span class=\"token function\">doHighlighting</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">IntentionAction</span> quickFixAction <span class=\"token operator\">=</span> myFixture<span class=\"token punctuation\">.</span><span class=\"token function\">findSingleIntention</span><span class=\"token punctuation\">(</span>intentionHint<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    myFixture<span class=\"token punctuation\">.</span><span class=\"token function\">launchAction</span><span class=\"token punctuation\">(</span>quickFixAction<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    myFixture<span class=\"token punctuation\">.</span><span class=\"token function\">checkResultByFile</span><span class=\"token punctuation\">(</span>testName <span class=\"token operator\">+</span> <span class=\"token string\">\".after.java\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Complete source code can be found at github <a href=\"https://github.com/pczekaj/tutorial-intellij-plugin\">github</a></p>\n<h2>Next steps</h2>\n<p>If you would like to share your plugin with other developers, you can publish to JetBrains plugin repository as described in the documentation. Other simple option is to execute buildPlugin Gradle task which will create plugin zip file inside build/distributions and then install it via <em>Install Plugin from disk...</em> available inside <em>Preferences > Plugins</em> (in IntelliJ 2018.3 is available through \"gears icon\").</p>\n<p>When working on your own ideas you might run into a situation when you don't know how to implement some functionality. In this situation you could try to find the answer using links provided in section below. What also worked for us was reading source code of inspections available as part of community edition of IntelliJ, often there is an existing inspection which does a similar thing to what you might want to do.</p>\n<h2>Links</h2>\n<ul>\n<li><a href=\"http://www.jetbrains.org/intellij/sdk/docs/faq.html\">IntelliJ SDK FAQ</a></li>\n<li><a href=\"https://github.com/JetBrains/intellij-sdk-docs/blob/master/tutorials/code_inspections.md\">Code inspections tutorial</a></li>\n<li><a href=\"https://intellij-support.jetbrains.com/hc/en-us/community/topics/200366979-IntelliJ-IDEA-Open-API-and-Plugin-Development\">Plugin development forum</a></li>\n<li><a href=\"https://github.com/JetBrains/intellij-community\">Source code of IntelliJ community edition</a></li>\n<li><a href=\"https://github.com/JetBrains/intellij-plugins\">Source code of many IntelliJ plugins</a></li>\n</ul>","fields":{"slug":"/intellij-plugin/","tags":["intellij"]}}},{"node":{"id":"df094608-f958-5bcd-b406-ea359067fbd8","frontmatter":{"category":"Coding","title":"PostgreSQL 12 - a precious release","date":"2019-10-29","summary":"Improved Common Table Expressions in recent release of Postgres","thumbnail":{"relativePath":"pages/postgres12-a-precious-release/elephant_cropped.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAWABQDASIAAhEBAxEB/8QAGQABAQADAQAAAAAAAAAAAAAAAAMBAgQF/8QAFgEBAQEAAAAAAAAAAAAAAAAAAQIA/9oADAMBAAIQAxAAAAHuzwyh9NJUx1M1Cf/EABoQAAIDAQEAAAAAAAAAAAAAAAEDABESAhD/2gAIAQEAAQUC9ZwwnDAsaq5ZgM//xAAYEQADAQEAAAAAAAAAAAAAAAAAARICE//aAAgBAwEBPwGDmxaZbP/EABcRAAMBAAAAAAAAAAAAAAAAAAACEwH/2gAIAQIBAT8BoVU1MJqf/8QAGxAAAgEFAAAAAAAAAAAAAAAAADEBECAhQWH/2gAIAQEABj8CrPIwNM1Z/8QAHBABAAICAwEAAAAAAAAAAAAAAQARITEQQVFx/9oACAEBAAE/IVDbLPeEWs5BNbatDthqyfsUeMAiBon/2gAMAwEAAgADAAAAEL/Xfv/EABkRAQEAAwEAAAAAAAAAAAAAAAEAMUFRYf/aAAgBAwEBPxAOy4kkzet//8QAGREAAwADAAAAAAAAAAAAAAAAAAExEVFh/9oACAECAQE/EHnGb2IuHE//xAAdEAEAAgICAwAAAAAAAAAAAAABABEhMRBRYXGh/9oACAEBAAE/EFAAVogmhwCxZXVnre/cLABvFBlrzTMCB1e/kSbKO4RYmd3m4ZIf/9k=","width":292,"height":325,"src":"/static/5076cf686ef8d2a21a3a6da9bf016970/a2998/elephant_cropped.jpg","srcSet":"/static/5076cf686ef8d2a21a3a6da9bf016970/a2998/elephant_cropped.jpg 1x,\n/static/5076cf686ef8d2a21a3a6da9bf016970/99cce/elephant_cropped.jpg 1.5x,\n/static/5076cf686ef8d2a21a3a6da9bf016970/6e995/elephant_cropped.jpg 2x,\n/static/5076cf686ef8d2a21a3a6da9bf016970/968b1/elephant_cropped.jpg 3x"}}},"authorName":"Mariusz Nowak","authorDescription":"Mariusz is a Senior Software Engineer at AUTO1 Group.","authorAvatar":null,"headerImage":null},"html":"<p>The PostgreSQL team <a href=\"https://www.postgresql.org/about/news/1976/\">announced recently</a> a new release of the most advanced\nopen source relational database - PostgreSQL 12. As usual it comes with an impressive list of improvements\n(generated columns ♥️), one of them being long awaited by dozens of developers: <strong>improved Common Table Expressions</strong>.</p>\n<p>I should first explain what are the Common Table Expressions for those who are unfamiliar with them:\nthe CTE’s, often called <code class=\"language-text\">“WITH queries”</code>, are SQL constructs giving a possibility of creating <strong>temporal data views</strong> for a sake of a query execution.</p>\n<p>Essentially CTE is an additional query which results can be referenced in the subsequent CTE’s or the main query before which\nit is being placed. It should be clear enough with an example - here’s a sample query with two CTE’s taken from Postgres docs:</p>\n<div class=\"gatsby-highlight\" data-language=\"sql\"><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">WITH</span> regional_sales <span class=\"token keyword\">AS</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token keyword\">SELECT</span> region<span class=\"token punctuation\">,</span> <span class=\"token function\">SUM</span><span class=\"token punctuation\">(</span>amount<span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span> total_sales\n    <span class=\"token keyword\">FROM</span> orders\n    <span class=\"token keyword\">GROUP</span> <span class=\"token keyword\">BY</span> region\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> top_regions <span class=\"token keyword\">AS</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token keyword\">SELECT</span> region\n    <span class=\"token keyword\">FROM</span> regional_sales\n    <span class=\"token keyword\">WHERE</span> total_sales <span class=\"token operator\">></span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> <span class=\"token function\">SUM</span><span class=\"token punctuation\">(</span>total_sales<span class=\"token punctuation\">)</span><span class=\"token operator\">/</span><span class=\"token number\">10</span> <span class=\"token keyword\">FROM</span> regional_sales<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">SELECT</span> region<span class=\"token punctuation\">,</span>\n       product<span class=\"token punctuation\">,</span>\n       <span class=\"token function\">SUM</span><span class=\"token punctuation\">(</span>quantity<span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span> product_units<span class=\"token punctuation\">,</span>\n       <span class=\"token function\">SUM</span><span class=\"token punctuation\">(</span>amount<span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span> product_sales\n<span class=\"token keyword\">FROM</span> orders\n<span class=\"token keyword\">WHERE</span> region <span class=\"token operator\">IN</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> region <span class=\"token keyword\">FROM</span> top_regions<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">GROUP</span> <span class=\"token keyword\">BY</span> region<span class=\"token punctuation\">,</span> product<span class=\"token punctuation\">;</span></code></pre></div>\n<p>Now we know what they are, but what purpose can they serve us? Well - we could parry here and say: for the same purpose as ordinary database views serve.\nThat’s of course a dramatic simplification - CTE’s are much more powerful and should not be treated as a simple database views.\nNevertheless I would like to keep the collation for the sake of this article.</p>\n<p>Database views are absolutely optional - one can simply substitute them with a subquery and achieve identical results.\nIndeed that’s what modern database engines do these days - once a database view is being used they inline it’s query as a subquery.\nWhy to bother then? We are able to deal completely without database views and even if we did use one the database engine would get rid of it anyway.</p>\n<p>What benefits do views give us then? And why the heck are they inlined?</p>\n<h3>The beauty of database views</h3>\n<p>The most appropriate explanation here is that database views help us achieve better readability.\nThey offer an elegant way of abstracting some parts of a database into a meaningful object, often matching closely with the domain.</p>\n<p>Instead of creating giant and ugly looking queries it is possible to extract some of its parts into an appealing view which is easier to browse and select data from. <strong>\"Divide and conquer\"</strong> rule in it’s true form.</p>\n<p>Still, we didn’t answer the fact that the underlying view’s query is most of the times <strong>inlined</strong> while it is being referenced. The reason is <strong>performance</strong> of course. Smart guys found out that lazy evaluation helps the optimizer a lot - by delaying the execution we could take advantage of a context of the actual query.</p>\n<p>This in turn allows many clever optimization techniques, like: pushing down predicates (<em>WHERE filters</em>), eliminating unnecessary <em>JOINS</em>, accessing only subset of columns etc.\nIn other words - a database is smart enough to do as little work as possible when evaluating database views, in the context of the issued query.</p>\n<p>Personally I love this pattern: aggregating all the data into views and letting a database to optimize my queries - these folks are really good in it and my queries are dead simple too.</p>\n<p>I have mentioned the CTE’s at the beginning, saying they are able to create temporal data views. I still conform to the comparison with database views - they both are in many cases similar.\nThe main difference is that CTE results are temporary and are reachable only in the context of a query which CTE is being part of.</p>\n<p>It may make sense to use a CTE in a place where a regular database view is not justified (e.g. it makes sense only in the context of a query and not in the whole domain), expecting similar behavior.</p>\n<h3>An ugly brother</h3>\n<p>Besides many remarkable advantages there’s at least one disadvantage which disqualifies CTE's for most use cases - before PostgreSQL 12 it was implemented as an <strong>optimization fence</strong>. What does it mean?</p>\n<p>Easy to imagine an example with a generic data view aggregating lots of data. If the view is then used to select just few records it could mean a tremendous waste of computation, if the aggregation is executed immediately.\nInstead the aggregation should be executed only on a small subset of data, which can be deduced from the outer query.</p>\n<p>Unfortunately such counter intuitive behavior was true for CTE’s for a long time - their results were <strong>materialized</strong> only to be accessible for the rest of the query afterwards.</p>\n<p>Not to blame anybody - the creators had quite good reasons to implement such behavior (i.e. guarantee of exactly one evaluation, possibility of a recursive CTE’s and more) but this still feels like focusing on corner cases instead of optimizing the happy path.\nThat’s why the community <a href=\"https://www.postgresql.org/message-id/flat/201209191305.44674.db%40kavod.com\">insisted for a long time</a> for changing the status quo by giving the possibility of disabling the fence and unlocking the full potential of CTE’s.</p>\n<h3>Game changer</h3>\n<p>The SQL gods listen to their prayers and here it is - PostgreSQL 12 with updated <a href=\"https://www.postgresql.org/docs/12/queries-with.html\">Common Table Expressions</a>.\nBy default, when few constraints are met, the queries will be inlined allowing joint optimizations.</p>\n<p>It is still possible to force the old behavior - by defining the CTE <code class=\"language-text\">AS MATERIALIZED</code> the engine would execute it immediately.\nIt is also possible to hint the optimizer that we definitely want the CTE to be inlined, e.g. when the CTE is being referenced twice the engine won't inline it by default.</p>\n<p>This is truly a game changer for many developers who care about their queries’ readability, allowing them to substitute not very well liked subqueries with elegant <code class=\"language-text\">“WITH queries”</code>.</p>\n<p>Don’t get me wrong - not every subquery should be immediately replaced, they still have their strengths and in some cases they should be chosen over CTE’s. It is just convenient to have two distinct tools in a toolbox, isn’t it?</p>","fields":{"slug":"/postgres12-a-precious-release/","tags":["postgres","postgres12","release","sql","cte"]}}},{"node":{"id":"24fd2709-272a-5811-a69c-7100924de21c","frontmatter":{"category":"Coding","title":"Serving JSON (almost) directly from database","date":"2019-10-29","summary":"Learn how to query JSON data from Postgres 12 to improve Java application's performance.","thumbnail":{"relativePath":"pages/serving-json-from-postgres/liberty.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAIDBAX/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIQAxAAAAHryz0HUYxXEAP/xAAbEAABBAMAAAAAAAAAAAAAAAABAgMSIhAgIf/aAAgBAQABBQJw0SoKxLjVDPT/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAYEAACAwAAAAAAAAAAAAAAAAABIQAQIP/aAAgBAQAGPwJRGzn/xAAaEAEAAwADAAAAAAAAAAAAAAABABEhEDGB/9oACAEBAAE/IVEqq3yWWlcbozCOmOokIz//2gAMAwEAAgADAAAAEOAPAP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8QH//EABwQAQADAQADAQAAAAAAAAAAAAEAETEhQXGhwf/aAAgBAQABPxBIyYq1CL8uc5XU14YIGwTYJTDeFrX2G/k7OwjIAbIBek//2Q==","width":325,"height":325,"src":"/static/e0de7302edcea3d0b0c19a9d147b547a/a2998/liberty.jpg","srcSet":"/static/e0de7302edcea3d0b0c19a9d147b547a/a2998/liberty.jpg 1x,\n/static/e0de7302edcea3d0b0c19a9d147b547a/99cce/liberty.jpg 1.5x,\n/static/e0de7302edcea3d0b0c19a9d147b547a/6e995/liberty.jpg 2x,\n/static/e0de7302edcea3d0b0c19a9d147b547a/968b1/liberty.jpg 3x"}}},"authorName":"Mariusz Nowak","authorDescription":"Mariusz is a Senior Software Engineer at AUTO1 Group.","authorAvatar":null,"headerImage":null},"html":"<p>RESTful API’s are ruling the industry nowadays. They are very often associated with an extremely popular data format - JSON.\nIt is so popular that database creators decided to implement it directly in the database engines.\nAll modern databases offer JSON processing capabilities.\nLet’s have a look and see how can we make use of them to improve our application’s performance.</p>\n<h3>JPA or JDBC?</h3>\n<p>The typical choice for a Java application is to use JPA as the persistence layer abstraction.\nIt became the de-facto standard for a reason - it offers great flexibility and ease of use.\nUnfortunately it doesn't come without a price since we have to pay with degraded performance.</p>\n<p>It is a widely known fact that <strong>ORM’s impact performance</strong>, compared to pure JDBC.\nOn the other hand, relatively few are willing to use plain JDBC, considering the amount of additional work it requires.</p>\n<p>Let me demonstrate how to use JDBC to leverage the performance, with the help of modern Postgres features.</p>\n<h3>Demo time</h3>\n<p>I have prepared a <a href=\"https://github.com/auto1-oss/postgres12-json-demo\">demo application</a> running on Spring Boot which exposes example data from the <a href=\"https://github.com/pthom/northwind_psql\">northwind</a> database.\nThe data are exposed in three different ways.</p>\n<p>The baseline version simply exposes JPA entities:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@GetMapping</span><span class=\"token punctuation\">(</span>path <span class=\"token operator\">=</span> <span class=\"token string\">\"/v1/orders/{order_id}\"</span><span class=\"token punctuation\">,</span>\n            produces <span class=\"token operator\">=</span> APPLICATION_JSON_VALUE<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">public</span> <span class=\"token class-name\">Order</span> <span class=\"token function\">getEntity</span><span class=\"token punctuation\">(</span><span class=\"token annotation punctuation\">@PathVariable</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"order_id\"</span><span class=\"token punctuation\">)</span> <span class=\"token class-name\">Integer</span> orderId<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> orderRepository<span class=\"token punctuation\">.</span><span class=\"token function\">findById</span><span class=\"token punctuation\">(</span>orderId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">orElseThrow</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>The Order entity aggregates data from numerous database tables: <code class=\"language-text\">orders</code>, <code class=\"language-text\">order_details</code>, <code class=\"language-text\">products</code>, <code class=\"language-text\">customers</code>, <code class=\"language-text\">customer_customer_demo</code> and <code class=\"language-text\">customer_demographics</code>.\nYou could check the corresponding JPA mapping <a href=\"https://github.com/auto1-oss/postgres12-json-demo/tree/postgres-12/src/main/java/com/auto1/postgres12/jpa\">here</a>.</p>\n<p>Thanks to the magic of Spring the entity is being translated into a JSON response:</p>\n<div class=\"gatsby-highlight\" data-language=\"json\"><pre class=\"language-json\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"orderId\"</span><span class=\"token operator\">:</span> <span class=\"token number\">10284</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"employeeId\"</span><span class=\"token operator\">:</span> <span class=\"token number\">4</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"orderDate\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"1996-08-19\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"requiredDate\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"1996-09-16\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"shippedDate\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"1996-08-27\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"shipVia\"</span><span class=\"token operator\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"freight\"</span><span class=\"token operator\">:</span> <span class=\"token number\">76.56</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"shipName\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Lehmanns Marktstand\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"shipAddress\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Magazinweg 7\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"shipCity\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Frankfurt a.M.\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"shipRegion\"</span><span class=\"token operator\">:</span> <span class=\"token null keyword\">null</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"shipPostalCode\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"60528\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"shipCountry\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Germany\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"orderDetails\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token property\">\"orderId\"</span><span class=\"token operator\">:</span> <span class=\"token number\">10284</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"productId\"</span><span class=\"token operator\">:</span> <span class=\"token number\">27</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"product\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token property\">\"productId\"</span><span class=\"token operator\">:</span> <span class=\"token number\">27</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"categoryId\"</span><span class=\"token operator\">:</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"supplierId\"</span><span class=\"token operator\">:</span> <span class=\"token number\">11</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"productName\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Schoggi Schokolade\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"discontinued\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"quantityPerUnit\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"100 - 100 g pieces\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"unitPrice\"</span><span class=\"token operator\">:</span> <span class=\"token number\">43.9</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"unitsInStock\"</span><span class=\"token operator\">:</span> <span class=\"token number\">49</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"unitsOnOrder\"</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"reorderLevel\"</span><span class=\"token operator\">:</span> <span class=\"token number\">30</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"unitPrice\"</span><span class=\"token operator\">:</span> <span class=\"token number\">35.1</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"quantity\"</span><span class=\"token operator\">:</span> <span class=\"token number\">15</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"discount\"</span><span class=\"token operator\">:</span> <span class=\"token number\">0.25</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">{</span>...<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">{</span>...<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">{</span>...<span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"customer\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"customerId\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"LEHMS\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"companyName\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Lehmanns Marktstand\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"contactName\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Renate Messner\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"contactTitle\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Sales Representative\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"address\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Magazinweg 7\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"city\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Frankfurt a.M.\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"region\"</span><span class=\"token operator\">:</span> <span class=\"token null keyword\">null</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"postalCode\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"60528\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"country\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Germany\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"phone\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"069-0245984\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"fax\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"069-0245874\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"customerDesc\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n      <span class=\"token punctuation\">{</span>\n        <span class=\"token property\">\"customerTypeId\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"AAAA\"</span><span class=\"token punctuation\">,</span>\n        <span class=\"token property\">\"customerDesc\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"First demographic\"</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">{</span>...<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">{</span>...<span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">{</span>...<span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">]</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>The demo project includes the p6spy library which gives an insight into the queries being issued against database.\nTurns out that <strong>three queries</strong> are required to load a particular Order - this means <strong>three database round trips</strong>.</p>\n<p>Of course we can force the ORM to join all the tables and fetch them in one hop, but this seems a not so elegant solution -\nit pushes the ORM to load duplicated data and the necessity of deduplicating them in-memory. Can we do better?</p>\n<h3>JDBC to the rescue</h3>\n<p>JDBC is always a choice if the solution could be expressed via SQL query. Luckily we can create one which matches our case perfectly:</p>\n<div class=\"gatsby-highlight\" data-language=\"sql\"><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token keyword\">WITH</span> products<span class=\"token punctuation\">(</span><span class=\"token string\">\"productId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"categoryId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"supplierId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"productName\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"discontinued\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"quantityPerUnit\"</span><span class=\"token punctuation\">,</span>\n              <span class=\"token string\">\"unitPrice\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"unitsInStock\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"unitsOnOrder\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"reorderLevel\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span>\n         <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> p<span class=\"token punctuation\">.</span>product_id<span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>category_id<span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>supplier_id<span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>product_name<span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>discontinued::<span class=\"token keyword\">boolean</span><span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>quantity_per_unit<span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>unit_price<span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>units_in_stock<span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>units_on_order<span class=\"token punctuation\">,</span>\n                 p<span class=\"token punctuation\">.</span>reorder_level\n          <span class=\"token keyword\">FROM</span> products p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n     orderDetails<span class=\"token punctuation\">(</span><span class=\"token string\">\"orderId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"productId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"product\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"unitPrice\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"quantity\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"discount\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span>\n         <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> d<span class=\"token punctuation\">.</span>order_id<span class=\"token punctuation\">,</span>\n                 d<span class=\"token punctuation\">.</span>product_id<span class=\"token punctuation\">,</span>\n                 <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> to_json<span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span> <span class=\"token keyword\">FROM</span> products p <span class=\"token keyword\">WHERE</span> p<span class=\"token punctuation\">.</span><span class=\"token string\">\"productId\"</span> <span class=\"token operator\">=</span> d<span class=\"token punctuation\">.</span>product_id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                 d<span class=\"token punctuation\">.</span>unit_price<span class=\"token punctuation\">,</span>\n                 d<span class=\"token punctuation\">.</span>quantity<span class=\"token punctuation\">,</span>\n                 d<span class=\"token punctuation\">.</span>discount\n          <span class=\"token keyword\">FROM</span> order_details d<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n\n     demographics<span class=\"token punctuation\">(</span><span class=\"token string\">\"customerId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"customerTypeId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"customerDesc\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span>\n         <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> ccd<span class=\"token punctuation\">.</span>customer_id<span class=\"token punctuation\">,</span>\n                 ccd<span class=\"token punctuation\">.</span>customer_type_id<span class=\"token punctuation\">,</span>\n                 cd<span class=\"token punctuation\">.</span>customer_desc\n          <span class=\"token keyword\">FROM</span> customer_demographics cd\n                   <span class=\"token keyword\">JOIN</span> customer_customer_demo ccd <span class=\"token keyword\">on</span> cd<span class=\"token punctuation\">.</span>customer_type_id <span class=\"token operator\">=</span> ccd<span class=\"token punctuation\">.</span>customer_type_id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n     customers<span class=\"token punctuation\">(</span><span class=\"token string\">\"customerId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"companyName\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"contactName\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"contactTitle\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"address\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"city\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"region\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"postalCode\"</span><span class=\"token punctuation\">,</span>\n               <span class=\"token string\">\"country\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"phone\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"fax\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"customerDesc\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span>\n         <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> c<span class=\"token punctuation\">.</span>customer_id<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>company_name<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>contact_name<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>contact_title<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>address<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>city<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>region<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>postal_code<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>country<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>phone<span class=\"token punctuation\">,</span>\n                 c<span class=\"token punctuation\">.</span>fax<span class=\"token punctuation\">,</span>\n                 <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> to_json<span class=\"token punctuation\">(</span>array_agg<span class=\"token punctuation\">(</span>to_json<span class=\"token punctuation\">(</span>d<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">FROM</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> <span class=\"token string\">\"customerTypeId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"customerDesc\"</span> <span class=\"token keyword\">FROM</span> demographics <span class=\"token keyword\">WHERE</span> demographics<span class=\"token punctuation\">.</span><span class=\"token string\">\"customerId\"</span> <span class=\"token operator\">=</span> c<span class=\"token punctuation\">.</span>customer_id<span class=\"token punctuation\">)</span> d<span class=\"token punctuation\">)</span>\n          <span class=\"token keyword\">FROM</span> customers c<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n\n     orders<span class=\"token punctuation\">(</span><span class=\"token string\">\"orderId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"employeeId\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"orderDate\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"requiredDate\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"shippedDate\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"shipVia\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"freight\"</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">\"shipName\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"shipAddress\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"shipCity\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"shipRegion\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"shipPostalCode\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"shipCountry\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"orderDetails\"</span><span class=\"token punctuation\">,</span>\n            <span class=\"token string\">\"customer\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span>\n         <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> o<span class=\"token punctuation\">.</span>order_id<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>employee_id<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>order_date<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>required_date<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>shipped_date<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>ship_via<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>freight<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>ship_name<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>ship_address<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>ship_city<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>ship_region<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>ship_postal_code<span class=\"token punctuation\">,</span>\n                 o<span class=\"token punctuation\">.</span>ship_country<span class=\"token punctuation\">,</span>\n                 <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> to_json<span class=\"token punctuation\">(</span>array_agg<span class=\"token punctuation\">(</span>to_json<span class=\"token punctuation\">(</span>d<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">FROM</span> orderDetails d <span class=\"token keyword\">WHERE</span> d<span class=\"token punctuation\">.</span><span class=\"token string\">\"orderId\"</span> <span class=\"token operator\">=</span> o<span class=\"token punctuation\">.</span>order_id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                 <span class=\"token punctuation\">(</span><span class=\"token keyword\">SELECT</span> to_json<span class=\"token punctuation\">(</span>c<span class=\"token punctuation\">)</span> <span class=\"token keyword\">FROM</span> customers c <span class=\"token keyword\">WHERE</span> c<span class=\"token punctuation\">.</span><span class=\"token string\">\"customerId\"</span> <span class=\"token operator\">=</span> o<span class=\"token punctuation\">.</span>customer_id<span class=\"token punctuation\">)</span>\n          <span class=\"token keyword\">FROM</span> orders o<span class=\"token punctuation\">)</span>\n\n<span class=\"token keyword\">SELECT</span> to_json<span class=\"token punctuation\">(</span>orders<span class=\"token punctuation\">)</span> <span class=\"token keyword\">AS</span> json_body <span class=\"token keyword\">FROM</span> orders <span class=\"token keyword\">WHERE</span> orders<span class=\"token punctuation\">.</span><span class=\"token string\">\"orderId\"</span> <span class=\"token operator\">=</span> ?</code></pre></div>\n<p>The query looks verbose, perhaps a little enigmatic.\nIt is a bit long and therefore it could be overwhelming.\nHowever, on a closer look we could notice it isn't so much complicated - there are few idioms which make the query powerful.</p>\n<p>The good news is that the query generates the exact same JSON as the JPA endpoint provides - it is possible thanks to Postgres’ excellent support for JSON format.\nOur case is not sophisticated though - single <code class=\"language-text\">to_json</code> function is enough to deal with JSON objects and arrays.</p>\n<p>One can notice how the nesting has been realized: how to nest JSON objects and JSON arrays, e.g. the <code class=\"language-text\">orderDetails</code> or the <code class=\"language-text\">customer</code> into <code class=\"language-text\">order</code>).\nThe simple idiom (accordingly <code class=\"language-text\">to_json(...)</code> or <code class=\"language-text\">to_json(array_agg(to_json(...)))</code>) does the job.</p>\n<p>The database query could be adapted according to the caller needs - the response can be shrinked, making the query simpler and - most probably - even more effective.</p>\n<p>Worth noticing is that the join table <code class=\"language-text\">customer_customer_demo</code> has been mitigated in the end result, just like the JPA version does by using <code class=\"language-text\">@ManyToMany</code>.</p>\n<hr>\n<blockquote>\n<p><em>The query is flexible enough to substitute all JPA features we need.</em></p>\n</blockquote>\n<hr>\n<p>I want also emphasize the fact of CTE’s being used to decompose the query into logical parts.\nPersonally I find it elegant because it is easy on the eyes and it “scales” - meaning while our case gets more complicated (JSON aggregates more data, becomes deeply nested) our query gets longer instead of getting deeper.\nIf the query grows too long we can simplify it by extracting some it’s parts as database views.</p>\n<p>The CTE has one more advantage here: it gives a control over the keys visible in end resulting JSON (<code class=\"language-text\">order_id</code> becomes <code class=\"language-text\">orderId</code>).</p>\n<p>So we have a nice query which allows us to fetch required data in one hop in a format ready to be consumed by our clients.\nThis means no adjustments are required, therefore the Java implementation can be that easy:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@SneakyThrows</span>\n<span class=\"token annotation punctuation\">@GetMapping</span><span class=\"token punctuation\">(</span>path <span class=\"token operator\">=</span> <span class=\"token string\">\"/v2/orders/{order_id}\"</span><span class=\"token punctuation\">,</span>\n            produces <span class=\"token operator\">=</span> APPLICATION_JSON_VALUE<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">public</span> <span class=\"token class-name\">String</span> <span class=\"token function\">getRawBodyFromDatabase</span><span class=\"token punctuation\">(</span>\n            <span class=\"token annotation punctuation\">@PathVariable</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"order_id\"</span><span class=\"token punctuation\">)</span> <span class=\"token class-name\">Integer</span> orderId<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> jdbcTemplate<span class=\"token punctuation\">.</span><span class=\"token function\">query</span><span class=\"token punctuation\">(</span>JSON_QUERY<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">ResultSet</span> rs<span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n        rs<span class=\"token punctuation\">.</span><span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> rs<span class=\"token punctuation\">.</span><span class=\"token function\">getString</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> orderId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We didn’t use plain JDBC here but a <code class=\"language-text\">JdbcTemplate</code> which has a negligible overhead and it simplifies our code.</p>\n<p>Of course we could achieve similar results using plain JDBC (e.g. by using <code class=\"language-text\">PreparedStatement</code> directly) - without the use of Spring.\nEven then the necessity of extracting only a single field from the result set makes the solution less coarse than using JDBC in a usual way\n(in our case it would require managing at least three result sets).\nAll the complexity has been moved down into the query.</p>\n<h3>But I need a POJO!</h3>\n<p>Some folks could argue “I don’t want the JSON to be directly returned - I definitely need the POJO to make some processing over it”.\nThat's an absolutely fair statement! We can satisfy this requirement as well.</p>\n<p>Let’s point it one more time: our query produces the exact same JSON as the Order JPA entity has been translated into.</p>\n<p>This means we can use the resulting JSON and unmarshall it into an object of class <code class=\"language-text\">Order</code>.\nOf course the object won’t be tracked by the JPA whatsoever but we don’t need these capabilities - remember: we are serving persisted data and not mutating them.</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@SneakyThrows</span>\n<span class=\"token annotation punctuation\">@GetMapping</span><span class=\"token punctuation\">(</span>path <span class=\"token operator\">=</span> <span class=\"token string\">\"/v3/orders/{order_id}\"</span><span class=\"token punctuation\">,</span>\n            produces <span class=\"token operator\">=</span> APPLICATION_JSON_VALUE<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">public</span> <span class=\"token class-name\">Order</span> <span class=\"token function\">getEntityNotUsingJpa</span><span class=\"token punctuation\">(</span><span class=\"token annotation punctuation\">@PathVariable</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"order_id\"</span><span class=\"token punctuation\">)</span> <span class=\"token class-name\">Integer</span> orderId<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> jdbcTemplate<span class=\"token punctuation\">.</span><span class=\"token function\">query</span><span class=\"token punctuation\">(</span>JSON_QUERY<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token class-name\">ResultSet</span> rs<span class=\"token punctuation\">)</span> <span class=\"token operator\">-></span> <span class=\"token punctuation\">{</span>\n        rs<span class=\"token punctuation\">.</span><span class=\"token function\">next</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">return</span> <span class=\"token function\">unmarshall</span><span class=\"token punctuation\">(</span>rs<span class=\"token punctuation\">.</span><span class=\"token function\">getString</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Order</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> orderId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token annotation punctuation\">@SneakyThrows</span>\n<span class=\"token keyword\">private</span> <span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">T</span><span class=\"token punctuation\">></span></span> <span class=\"token class-name\">T</span> <span class=\"token function\">unmarshall</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">String</span> json_body<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Class</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">T</span><span class=\"token punctuation\">></span></span> clazz<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> objectMapper<span class=\"token punctuation\">.</span><span class=\"token function\">readValue</span><span class=\"token punctuation\">(</span>json_body<span class=\"token punctuation\">,</span> clazz<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>This version is very similar to V2 but it introduces an additional step of unmarshalling.\nIt is also a great verification step which makes us sure the V1 and V2 results are identical.</p>\n<h3>Measure, measure, measure</h3>\n<p>So how are all the solutions performing?\nWe suspect the V2 version to be faster than the competitors.\nWe are also unsure about the V3 which requires additional unmarshalling phase - could it impact the performance badly?</p>\n<p>The demo project includes a JMeter configuration and a bash script which verifies the configurations.\nThe benchmark is always run against a fresh setup (db + app).\nThe app is running on java 11 with EpsilonGC turned on - this allows us to verify memory consumption of each solution.</p>\n<p>The requests are run in strictly defined sequence, fetching the orders one by one.\nThere’s a prewarming phase which issues 100 requests and then a profiling phase with 20k of requests.</p>\n<p>I have run the benchmark several times on a Macbook Pro 2018, the results are similar on each run.\nHere’s a summary of the most recent run:</p>\n<ul>\n<li>V1 took <strong>1 minute and 25 seconds</strong> to complete the benchmark, the docker container ended up using <strong>1762 MB</strong> (1.641 GiB) of memory.</li>\n<li>V2 took <strong>53 seconds</strong> to complete the benchmark, the docker container ended up using <strong>1710 MB</strong> (1.593 GiB) of memory</li>\n<li>V3 took exactly <strong>1 minute</strong> to complete the benchmark, the docker container ended up using <strong>1758 MB</strong> (1.638 GiB) of memory</li>\n</ul>\n<p>We can see the V2 outperforming the V1 by 32 seconds - that’s <strong>37% improvement</strong>. </p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/00907e6fc534a6e242f935607d2ec10b/eb351/benchmark_duration.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 60.79207920792079%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAABYlAAAWJQFJUiTwAAABzklEQVQoz22TW0sbQRTH94tWUAQLRftmaYVC7ScoFgr60qdSaH31QcFCvaGmJoGkiZU21O1GN5vN3i+Znd1/5+zN3cSBH+fMzux/zmVGghhJkpTMDsZCyPIt7u/voKp3GI1UKIos5kOEoV/bS79LsyI8TuAHEYKAp3g+g2l5JZblwzSFtX14HkMQ0p5IHByTJKQiQsYiJDHD74GBl2+aNTbetkpebZJt5z6tNbH++gon56M0IKlINQhCkYKH65sxnr+4xFqNi4q9wOr6A/Sd7NGZmgnO1ozC7/YMdPumwKj42bzz00Dv2hQHW+j/ymy3Z0IbB5lgHMciXZZGyPkU/4YOtrb7c7wndvp496EHWfHw2IhF/SXOOVzXha5P4LmWOF3H0rNTLAqqtmB59QztziS/ATwVKaDSzaXsuAyN5hg/WnpKo/XgX7V1nDc00e1pHlFcXrWiF2nKRBTxdEEdefj05Y9gkCP8r4MM4X/eHWD74w06orZFmjVBStcwDGjaGI5NTdCwsHKCJyvHua2z8DTj+6n6uGDhUJR0MSdGgP3DIQ6+ZewfKqVfsHeg4K/sZoKVlElDmn9q05nOhdV3RDvKmW3boKbSiKIIjuPgP7PRWr4XqQUSAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Benchmark duration in seconds\"\n        title=\"\"\n        src=\"/static/00907e6fc534a6e242f935607d2ec10b/40fad/benchmark_duration.png\"\n        srcset=\"/static/00907e6fc534a6e242f935607d2ec10b/707e9/benchmark_duration.png 148w,\n/static/00907e6fc534a6e242f935607d2ec10b/649e0/benchmark_duration.png 295w,\n/static/00907e6fc534a6e242f935607d2ec10b/40fad/benchmark_duration.png 590w,\n/static/00907e6fc534a6e242f935607d2ec10b/b3fef/benchmark_duration.png 885w,\n/static/00907e6fc534a6e242f935607d2ec10b/eb351/benchmark_duration.png 1010w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>We can notice also a lower memory consumption on the V2 - it used <strong>52 MB</strong> (49 MiB) <strong>less memory</strong> than V1\n(noted the initial app’s memory usage which is 785 MB):</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/b7b44c0c52b828e9c0a6cc8124d4857a/b0617/memory_consumption_table.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 15.815815815815814%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAYAAACTWi8uAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAoUlEQVQI13WMyw6CMBBF+f9PkhQw3ahAAgYSCAt2ItJaRN5dXKeNceckNzlnXg7nRzDmgvMAQcCID/B9Bs9zrWdZiiSJEUVn5MR5niKOLwjDE/HVuplF5FVVwCnLAk1zw7ouGMe3zTRNXx6xzDOG4YW2vdsdk75X6LrHz6WUkEJg2zY4dV3TUOBfaa3p4UBHAnrfyXco9YSgB4ZNz7iJ2f0AaFLdIFy73HYAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Memory consumption comparison\"\n        title=\"\"\n        src=\"/static/b7b44c0c52b828e9c0a6cc8124d4857a/40fad/memory_consumption_table.png\"\n        srcset=\"/static/b7b44c0c52b828e9c0a6cc8124d4857a/707e9/memory_consumption_table.png 148w,\n/static/b7b44c0c52b828e9c0a6cc8124d4857a/649e0/memory_consumption_table.png 295w,\n/static/b7b44c0c52b828e9c0a6cc8124d4857a/40fad/memory_consumption_table.png 590w,\n/static/b7b44c0c52b828e9c0a6cc8124d4857a/b3fef/memory_consumption_table.png 885w,\n/static/b7b44c0c52b828e9c0a6cc8124d4857a/b0617/memory_consumption_table.png 999w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6101a2054a60731cc34de93dc5d69976/1a868/memory_consumption_chart.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 38.76146788990826%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABYlAAAWJQFJUiTwAAAB7ElEQVQozzWS228SQRSH+fP8C3z1wTeNIZJWY8Q+tKE1xodqDBa8tS/Gy5OmqTGmSq02xEShGG7lfimwC7uUsOwCy8znsOBJzlzOzHy/OWfGNxMCXdfpahp616Cvtempca1Wxx3b/DfXdZFSYltDtHYb0+hhGxo9XaPVbNJX87n55k3NhddN6QV+D6Cn5mM1flWXCLmIj2wFdye8aeG55Up2GxJtLIkZ8LSKt9dXLfSJHJvcK0Ai3mE1MeVdZsTHY50bGUVaAu2xkhBTgjnJWk7QcSSX4pLTgWRPCV9NLsR9nz/V8EdK3FcKj7dT3DyxCR8ZBLczBEtgOIKRM8Z2HA+4UYGQcn0iufwX0pbKrgPX88sbxr42ub1XY1NtehnNEIg7RH+abEbPuKuAVd2hcd5haKmTzHgQ6/PwyKRruVx5q5HVJrxPDVnZ7yKEAn47bHJrt8qWAj6PLIE/TEI7ee4UVcZikbLjzKsqCEey7ESzGMYYfyBOoThg/6DOeiixAB5+aRB4UWGjDJFwGv+JQ/i7wXo4z6qqq7sEuu7M6x9Fcjx5lqNnOFxb+UVeAT8cNFjbOlVAgc9QC6mSSckSVKsXJNtDzi9c0mddsoMpcvltZjMxfyGKZZNypc90KviTbKlSTGipM+ms7n2rf9gTOwkX5RGhAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Memory consumption comparison\"\n        title=\"\"\n        src=\"/static/6101a2054a60731cc34de93dc5d69976/40fad/memory_consumption_chart.png\"\n        srcset=\"/static/6101a2054a60731cc34de93dc5d69976/707e9/memory_consumption_chart.png 148w,\n/static/6101a2054a60731cc34de93dc5d69976/649e0/memory_consumption_chart.png 295w,\n/static/6101a2054a60731cc34de93dc5d69976/40fad/memory_consumption_chart.png 590w,\n/static/6101a2054a60731cc34de93dc5d69976/b3fef/memory_consumption_chart.png 885w,\n/static/6101a2054a60731cc34de93dc5d69976/301c0/memory_consumption_chart.png 1180w,\n/static/6101a2054a60731cc34de93dc5d69976/1a868/memory_consumption_chart.png 1308w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<hr>\n<blockquote>\n<p><em>Worth noticing: the V2 version does not leverage Hibernate at all therefore we could minimize the memory footprint even more by excluding the JPA dependencies.</em></p>\n</blockquote>\n<hr>\n<p>Let’s have a look at response times:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/73c8b2f75166508b24cc53407109875b/13a80/response_time_table.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 11.15107913669065%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsSAAALEgHS3X78AAAAhElEQVQI1z2Muw6CQBBF+f9v0cRlkdibGAE11Gohsj5Acd9ibK6zW1ic3Mk5ySRsdURaNEhLAV61YMUZfHNBRsy3N+R1R63FdLmn1sTGK0H9Su4Atj5hRkyoL3YCyb1/4jEoSG3hxy+kcXgpC2U8rP9EgtNujE7RHZDaYZAG2r7/G378APwJj8zXTZkxAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Response time summary\"\n        title=\"\"\n        src=\"/static/73c8b2f75166508b24cc53407109875b/40fad/response_time_table.png\"\n        srcset=\"/static/73c8b2f75166508b24cc53407109875b/707e9/response_time_table.png 148w,\n/static/73c8b2f75166508b24cc53407109875b/649e0/response_time_table.png 295w,\n/static/73c8b2f75166508b24cc53407109875b/40fad/response_time_table.png 590w,\n/static/73c8b2f75166508b24cc53407109875b/b3fef/response_time_table.png 885w,\n/static/73c8b2f75166508b24cc53407109875b/301c0/response_time_table.png 1180w,\n/static/73c8b2f75166508b24cc53407109875b/13a80/response_time_table.png 1668w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Once again we are able to notice improved throughput as well as lower latency.</p>\n<p>The plot confirms that as well (cropped for brevity):</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/609ca54ea332fb5f16d9c48de682d24f/4fbf1/response_time_plot.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 42.516069788797054%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsSAAALEgHS3X78AAAA60lEQVQoz6WS227EIAxE+f/v7G4gbIAQrgEyNaTdVdX2oaml0QEsWcPIbF1XpJQQQkCM8TJjTHBagfVhvY7j+Bd7Fe9eA1tro3mJ4wxkt50DR6PW0byq7jNvhgbmfFr/sP1XflZ3GPQM5p1D2zNK9CgpkPwX7dGRfmBwyKREuUVr4LXEZjXYwt+gxA0PfscyT5D8RuSDiqjozS4ztJywLgJ6flFLjoe4w5oFxijalgxWSkGlDGqjHMl2qW1wL3Wwv/sQoc06vlko65PtyUb/3fcysmSzlFDagAsBowT4RI6s/b6bpF938HmPeAfpVL+J2Dl0mAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Response time percentiles plot\"\n        title=\"\"\n        src=\"/static/609ca54ea332fb5f16d9c48de682d24f/40fad/response_time_plot.png\"\n        srcset=\"/static/609ca54ea332fb5f16d9c48de682d24f/707e9/response_time_plot.png 148w,\n/static/609ca54ea332fb5f16d9c48de682d24f/649e0/response_time_plot.png 295w,\n/static/609ca54ea332fb5f16d9c48de682d24f/40fad/response_time_plot.png 590w,\n/static/609ca54ea332fb5f16d9c48de682d24f/b3fef/response_time_plot.png 885w,\n/static/609ca54ea332fb5f16d9c48de682d24f/4fbf1/response_time_plot.png 1089w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Personally I am very well satisfied with the V3 results - the memory consumption being at the same level as the JPA it still offers satisfying performance, nearly as good as the V1.\nIt proves that the unmarshalling does not impact the performance as badly as we might expect.</p>\n<p>I really encourage readers try running the benchmark and share their own results!</p>\n<h3>Postgres 12 exclusive</h3>\n<p>Last words about the database: the results are reproducible currently only on Postgres 12,\ndue to <a href=\"/postgres12-a-precious-release\">recent improvements in Common Table Expressions</a>.</p>\n<p>I have had a run on Postgres 11 and the V2’s performance was… horrible - I had to shorten the benchmark 10 times to make it finish in a reasonable time.\nHere are the results I got:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/1f9adc4fa288d49948eed727adf6be02/25720/postgres11_plot.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 26.254180602006688%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAAAsSAAALEgHS3X78AAAAfElEQVQY06WQ4Q7DIAiEff/HraIIhSvMLWuamP2YyeWLd0KEwsxIicifUvAglForzBx53D2Eh8LDD65yqHA0PA7YqWGecNsoM7d9bitXGSg5LlGLsTt6J4z49od3tVbfWduQXn0KzxnGwJzfXczbXpKZERFEdb17UhY17hdUJojcyMhn+QAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Response time percentiles plot\"\n        title=\"\"\n        src=\"/static/1f9adc4fa288d49948eed727adf6be02/40fad/postgres11_plot.png\"\n        srcset=\"/static/1f9adc4fa288d49948eed727adf6be02/707e9/postgres11_plot.png 148w,\n/static/1f9adc4fa288d49948eed727adf6be02/649e0/postgres11_plot.png 295w,\n/static/1f9adc4fa288d49948eed727adf6be02/40fad/postgres11_plot.png 590w,\n/static/1f9adc4fa288d49948eed727adf6be02/b3fef/postgres11_plot.png 885w,\n/static/1f9adc4fa288d49948eed727adf6be02/301c0/postgres11_plot.png 1180w,\n/static/1f9adc4fa288d49948eed727adf6be02/b5a53/postgres11_plot.png 1770w,\n/static/1f9adc4fa288d49948eed727adf6be02/25720/postgres11_plot.png 1794w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>You can give it a try - the demo app is prepared to allow a quick switch to Postgres 11.</p>\n<h3>Summary</h3>\n<p>The query we have prepared enables fine control over the data being fetched from database.</p>\n<p>We are no longer restricted to tabular data - we could easily fetch complex data graphs, even manipulate them to match the desired format.\nWe did it keeping the solution maintainable and very effective in terms of throughput.</p>\n<p>It is still unknown to me what is the main source of latency in the JPA version: either is it the additional round trips or the internals of Hibernate.\nI see the topic interesting to explore.\nPerhaps some day we’ll get an ORM which is able to load entity graphs using a single query.\nAny Hibernate devs reading here?</p>","fields":{"slug":"/serving-json-from-postgres/","tags":["jdbc","jpa","postgres12","json","spring boot"]}}},{"node":{"id":"a7cdd55d-a270-5c8c-be42-5c2c15c043f0","frontmatter":{"category":"Coding","title":"Testing your isolated Fragments with Koin","date":"2019-09-09","summary":"This blog post explains how you could set up your environment in order to test your fragments in isolation from other parts of your application","thumbnail":{"relativePath":"pages/testing-isolated-fragments-with-koin/thumbnail.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEcklEQVQ4y5WUbUxTVxjHL2UxCouJbsk+7MvmErNsH7b4YX4wsg0nU6RbXEXKS3lxMCm1paGIaJ1ji04Z08Eob8MhaGCSwRZIkPEqVSgKZVJKLb194basyHiZa0tfGG2fPfde6sQsLjvJP885zznP7z7n3PMcYoksIZZNcoJuDuPZsBWzkEM81uA9gnCNH2N8MEgQDzWniKc25xS7wEEWhYV8S+aarQ7Tl286jOdfCvmW7whY6Nq4IjeRUEgSmX7IPmoO8gsG9rupIdJtkpd5TPmLXlK66tFLvMuTuSrH5Mld9Ly6jhuukKZxSnPiwy5kcNfASethf0ydZ2BWfctGt7HgNiwVwl+kCLy6o+CdyAK4nwm+sQxwjYl4T+4OwREh6JnD77JOnyEnnNm6vvBzmD8O3slPfB5NZsAzlh703E0OBEeTYGX0CFj7Zd+KuanPVUr5u74R8raVCg9t/+54+st0bFWeIOxc6j7iTPw7LPTexPgGlzaXDNzPAgQF3HdTgu4hftAzlAyLt4W3dL3F0ReFSdcVEv4qnpe/XMz3XcrmzRXx9zCEc6n7mfP9NH4tS7uufqtzTLjsG00GGuRW8vx+FR9mbxVU0fNfZ8W3VObydQgzVeYmAdpV3GZf8RHugpwXtYNe81lC9D+3Y3yiN+JPVaZ9ZegQuPoPBlxd3KC78wC4b8TOUs281rqTaXApJ3FBIU6AyzIB1OalgELMX7ySLwA8u19oRnFGXBiTIXRvZ8jzStE1GOaBqyPW52zbF3T+tDfoad0Dwba9MN/4PnReiH+gkH3cUJ2fVl+dn06rsUqW1nQ2dX8Rc50AiE10h7p5mgFODtZuW+xMXoTOGHA2v+13NkX5HVd3+53fvxVYbtgJv6kbneaZ+UkLRekslE1nsdq0ZspqGNdO9nR190TSDM3EBHuX7T1sJej6Lr4x15425mqJhZUfY8DdFA3z1z/ymYabA6TZBlZqGiiKYjU9DTarFUZGRpZ1Ot2NmZmZLew9vClg7IPetZLD1PU9X0VTHflZ5nZpnFar3m0wWb1GkgSDwRAIiSTJldnZWVCpVFKTySRHH1u/+r4Swt3O/m5bdx7n38qTNOi77XY70BBUkAYajcagVquFgYGB17BfjT7ho4B7vXXEw4549gPdJYSpU86xtYvCzYP1G2gfBuzELJitYqAfx2Cz2UCtVlN6vX4Ax7UajYbz1EcDAxk7NTXFLMTMeOhbslgsQMMR0IDZPY/AF0MxSqUybB3k8VcD+xxaZUIep+1y6TPMXxwbfcGg13+g007sIP5PKzuW8J9rrgxbnr2qWdhU9+tcRM3PvZtr1HORla1dG9ctol+NMlFCKMNorF1uuSQxhu6jPYzzUZUFmSkVhdlCRWF2uuLEUQEqQyEXf6g4kS2rOC15dR2wXJzInIFCnPgKQjRYXo1oe/AxaEJ4P/bvoK8KS1CJ+oFWOWs7Uf2ohCeA/JDdjMH5CI5DewrVgRKh/wBm+joqD8cHURKUEMfZaGUV0uQtfwP/KbEPkxHssgAAAABJRU5ErkJggg==","width":280,"height":280,"src":"/static/3002cc6db63b27d120e79145783a1750/b2831/thumbnail.png","srcSet":"/static/3002cc6db63b27d120e79145783a1750/b2831/thumbnail.png 1x"}}},"authorName":"Oleg Osipenko","authorDescription":"Senior Software Engineer","authorAvatar":{"relativePath":"pages/testing-isolated-fragments-with-koin/avatar.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAQDAf/EABYBAQEBAAAAAAAAAAAAAAAAAAIAA//aAAwDAQACEAMQAAABvxphrZG0EPTN4Bn/xAAcEAABBQADAAAAAAAAAAAAAAACAAEDERIEIUH/2gAIAQEAAQUCMe3HKpTU69LkszxyFqUy1a//xAAWEQADAAAAAAAAAAAAAAAAAAABIDH/2gAIAQMBAT8BET//xAAXEQADAQAAAAAAAAAAAAAAAAAAAREQ/9oACAECAQE/AW3S7//EABkQAQADAQEAAAAAAAAAAAAAAAEAEDERcf/aAAgBAQAGPwIJtFZFXvs2v//EABoQAQEBAQEBAQAAAAAAAAAAAAEAESExUWH/2gAIAQEAAT8hxA4Prax0i9GTYNSGfefshNWsqhiiOSvft//aAAwDAQACAAMAAAAQpBd//8QAGBEBAQADAAAAAAAAAAAAAAAAAQAQEUH/2gAIAQMBAT8QAzTcx//EABURAQEAAAAAAAAAAAAAAAAAABBB/9oACAECAQE/EAVP/8QAHBABAQEBAAIDAAAAAAAAAAAAAREAITFBgZHR/9oACAEBAAE/EGgFUPPPR96QjAi/JqtWdBTjHT0kCCvN/MUGjjrFKJRrNDGeA876ympRXm//2Q==","width":50,"height":50,"src":"/static/4d1dd08092290e44fd34c92f78d9904e/d2d31/avatar.jpg","srcSet":"/static/4d1dd08092290e44fd34c92f78d9904e/d2d31/avatar.jpg 1x,\n/static/4d1dd08092290e44fd34c92f78d9904e/0b804/avatar.jpg 1.5x,\n/static/4d1dd08092290e44fd34c92f78d9904e/753c3/avatar.jpg 2x,\n/static/4d1dd08092290e44fd34c92f78d9904e/31ca8/avatar.jpg 3x"}}},"headerImage":{"relativePath":"pages/testing-isolated-fragments-with-koin/headerImage.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAAAsSAAALEgHS3X78AAAAvklEQVQY02NggIIvV/LB9Pvb7WzfrmRs+Hw+vQgmt35mb+DqSS2fV01ujwLxF3dWMZ0/eYwBL/hwNIURRL+7USf8aVfQn/frfLp0p/xnD3JSZ7/14LHdvYePXt66ez8dpObk8WOMj1++wW+gMsiVW3zB7OcLfNVfLfbSALFvCTIwTMwINFrSWRU2rSzFqSXahQkkPqU4kYEo8Hm9F5x9Zl4qY//kOQxT8iI1OqKd5SZmhcouaCoEy03OjcCqHwADLUswHlaKbgAAAABJRU5ErkJggg==","width":1280,"height":280,"src":"/static/a77f9e0124a66d21b204dc560d751ee8/26421/headerImage.png","srcSet":"/static/a77f9e0124a66d21b204dc560d751ee8/26421/headerImage.png 1x"}}}},"html":"<p>UI-tests are a necessary part of our development routine in AUTO1. Although that wasn’t the case a while ago. One of the issues, which was blocking developers from writing and running UI-tests, was the need to set up UI-tests. Of course, to test the screen in isolation you need to have some architecture, employ the SOLID principles, especially Dependency inversion. With proper architecture it’s easy to substitute dependencies inside screen under the test with fakes or mocks. But even with good architecture you need to provide these mock implementations. And it’s not always obvious how to make your DI framework to provide mocks for tests.</p>\n<p>Recently we started a brand new project from scratch. And we decided to give <a href=\"https://insert-koin.io/\">Koin</a> a try. Why Koin and not Dagger? — Just because Koin offers concise and minimalistic syntax and it uses Kotlin. Also, important for us was the question of code generation. Although Google announced that in new versions of Android Gradle plug-in they made kapt incremental, we still didn’t want to add this extra burden to our build process. Simultaneously Koin 2.0 was announced at the same time. That’s how we found ourselves facing question: how to provide mock dependencies to our UI-tests?</p>\n<h2>Let’s start with fragment…</h2>\n<p>Inside our fragments we inject number of dependencies, typically they include viewmodels:</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">private</span> <span class=\"token keyword\">val</span> fragmentViewModel<span class=\"token operator\">:</span> EmailLoginFragmentViewModel <span class=\"token keyword\">by</span> <span class=\"token function\">viewModel</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>That’s exactly what we want to substitute with mocks. To do so we need a custom Application class, which will start Koin with our test module, not the real one.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">class</span> KoinTestApp<span class=\"token operator\">:</span> <span class=\"token function\">Application</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">onCreate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">.</span><span class=\"token function\">onCreate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    startKoin <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">androidLogger</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">androidContext</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token label symbol\">@KoinTestApp</span><span class=\"token punctuation\">)</span>\n    <span class=\"token function\">modules</span><span class=\"token punctuation\">(</span><span class=\"token function\">emptyList</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">internal</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">injectModule</span><span class=\"token punctuation\">(</span>module<span class=\"token operator\">:</span> Module<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">loadKoinModules</span><span class=\"token punctuation\">(</span>module<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We start our Koin instance inside <code class=\"language-text\">onCreate()</code> method, and we pass <code class=\"language-text\">emptyList()</code> of modules. We also have a method <code class=\"language-text\">injectModule()</code> which accepts our test module. Since we already started our application, we are using method <code class=\"language-text\">loadKoinModules()</code> to add this test module to the graph.</p>\n<h2>How to run custom application</h2>\n<p>But we need to somehow start our test application class. We cannot use <code class=\"language-text\">AndroidManifest</code>  inside <code class=\"language-text\">androidTest</code> folder, because manifest merger will ignore it if we set our test application inside Manifest like this: <code class=\"language-text\">&lt;application name=\".KoinTestApp\"></code>. So we could use a custom test runner for that purpose. <code class=\"language-text\">AndroidJUnitRunner</code> class has a <code class=\"language-text\">newApplication()</code> method. And we can pass our test application name there, making our test runner to start our test application instead of a real one.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">class</span> KoinTestRunner<span class=\"token operator\">:</span> <span class=\"token function\">AndroidJUnitRunner</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">newApplication</span><span class=\"token punctuation\">(</span>\n    cl<span class=\"token operator\">:</span> ClassLoader<span class=\"token operator\">?</span><span class=\"token punctuation\">,</span> \n    className<span class=\"token operator\">:</span> String<span class=\"token operator\">?</span><span class=\"token punctuation\">,</span> \n    context<span class=\"token operator\">:</span> Context<span class=\"token operator\">?</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Application <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">return</span> <span class=\"token keyword\">super</span><span class=\"token punctuation\">.</span><span class=\"token function\">newApplication</span><span class=\"token punctuation\">(</span>cl<span class=\"token punctuation\">,</span> KoinTestApp<span class=\"token operator\">::</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">.</span>java<span class=\"token punctuation\">.</span>name<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Then we need to change our <code class=\"language-text\">build.gradle</code> inside our app module:</p>\n<div class=\"gatsby-highlight\" data-language=\"groovy\"><pre class=\"language-groovy\"><code class=\"language-groovy\">android <span class=\"token punctuation\">{</span>\n  defaultConfig <span class=\"token punctuation\">{</span>\n    …\n    …\n    testInstrumentationRunner “path<span class=\"token punctuation\">.</span>to<span class=\"token punctuation\">.</span>your<span class=\"token punctuation\">.</span><span class=\"token keyword\">package</span><span class=\"token punctuation\">.</span>KoinTestRunner”\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And don’t forget to disable animations for UI-tests:</p>\n<div class=\"gatsby-highlight\" data-language=\"groovy\"><pre class=\"language-groovy\"><code class=\"language-groovy\">android <span class=\"token punctuation\">{</span>\n  testOptions <span class=\"token punctuation\">{</span>\n    animationsDisabled <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h2>Test rule for fragments</h2>\n<p>We are almost done. We only need to write our test and provide our test module to it. We are using our custom fragment test rule, which provides a couple of methods for submitting your fragment and mock test module. But you could use the same approach for activities.</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token keyword\">abstract</span> <span class=\"token keyword\">class</span> FragmentTestRule<span class=\"token operator\">&lt;</span>F<span class=\"token operator\">:</span> Fragment<span class=\"token operator\">></span><span class=\"token operator\">:</span> \n  ActivityTestRule<span class=\"token operator\">&lt;</span>FragmentActivity<span class=\"token operator\">></span><span class=\"token punctuation\">(</span>FragmentActivity<span class=\"token operator\">::</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">.</span>java<span class=\"token punctuation\">,</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  \n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">afterActivityLaunched</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">.</span><span class=\"token function\">afterActivityLaunched</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    activity<span class=\"token punctuation\">.</span><span class=\"token function\">runOnUiThread</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">val</span> fm <span class=\"token operator\">=</span> activity<span class=\"token punctuation\">.</span>supportFragmentManager\n      <span class=\"token keyword\">val</span> transaction <span class=\"token operator\">=</span> fm<span class=\"token punctuation\">.</span><span class=\"token function\">beginTransaction</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      transaction<span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span>android<span class=\"token punctuation\">.</span>R<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">.</span>content<span class=\"token punctuation\">,</span> <span class=\"token function\">createFragment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">.</span><span class=\"token function\">commit</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n  \n  <span class=\"token keyword\">override</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">beforeActivityLaunched</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">.</span><span class=\"token function\">beforeActivityLaunched</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">val</span> application <span class=\"token operator\">=</span> InstrumentationRegistry<span class=\"token punctuation\">.</span><span class=\"token function\">getInstrumentation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span>targetContext<span class=\"token punctuation\">.</span>applicationContext <span class=\"token keyword\">as</span> KoinTestApp\n    application<span class=\"token punctuation\">.</span><span class=\"token function\">injectModule</span><span class=\"token punctuation\">(</span><span class=\"token function\">getModule</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">protected</span> <span class=\"token keyword\">abstract</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">createFragment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> F\n  \n  <span class=\"token keyword\">protected</span> <span class=\"token keyword\">abstract</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">getModule</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Module\n  \n  <span class=\"token keyword\">fun</span> <span class=\"token function\">launch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">launchActivity</span><span class=\"token punctuation\">(</span><span class=\"token function\">Intent</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">fun</span> <span class=\"token operator\">&lt;</span>F<span class=\"token operator\">:</span> Fragment<span class=\"token operator\">></span> <span class=\"token function\">createRule</span><span class=\"token punctuation\">(</span>fragment<span class=\"token operator\">:</span> F<span class=\"token punctuation\">,</span> module<span class=\"token operator\">:</span> Module<span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> FragmentTestRule<span class=\"token operator\">&lt;</span>F<span class=\"token operator\">></span> <span class=\"token operator\">=</span> \n  <span class=\"token keyword\">object</span><span class=\"token operator\">:</span> FragmentTestRule<span class=\"token operator\">&lt;</span>F<span class=\"token operator\">></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">override</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">createFragment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> F <span class=\"token operator\">=</span> fragment\n\n    <span class=\"token keyword\">override</span> <span class=\"token keyword\">fun</span> <span class=\"token function\">getModule</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span> Module <span class=\"token operator\">=</span> module\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>I am using default Android <code class=\"language-text\">FragmentActivity</code> to host fragment under test. So we need to mention this activity in the manifest. For that purpose I created instance of <code class=\"language-text\">AndroidManifest</code> inside debug variant in my app module:</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token prolog\">&lt;?xml version=\"1.0\" encoding=\"utf-8\"?></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>manifest</span>\n  <span class=\"token attr-name\"><span class=\"token namespace\">xmlns:</span>android</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>http://schemas.android.com/apk/res/android<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">package</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>com.github.olegosipenko.kointestsample<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>application</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>activity</span>\n      <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>theme</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>@style/AppTheme<span class=\"token punctuation\">\"</span></span>\n      <span class=\"token attr-name\"><span class=\"token namespace\">android:</span>name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>androidx.fragment.app.FragmentActivity<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">/></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>application</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>manifest</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<h2>Test itself</h2>\n<p>Finally, our test class could look like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"kotlin\"><pre class=\"language-kotlin\"><code class=\"language-kotlin\"><span class=\"token annotation builtin\">@RunWith</span><span class=\"token punctuation\">(</span>AndroidJUnit4ClassRunner<span class=\"token operator\">::</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">class</span> EmailLoginFragmentTest <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">val</span> fragmentViewModel<span class=\"token operator\">:</span> EmailLoginFragmentViewModel <span class=\"token operator\">=</span> <span class=\"token function\">mockk</span><span class=\"token punctuation\">(</span>relaxed <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span>\n  <span class=\"token keyword\">private</span> <span class=\"token keyword\">val</span> fragment <span class=\"token operator\">=</span> <span class=\"token function\">EmailLoginFragment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token annotation builtin\">@get:Rule</span>\n  <span class=\"token keyword\">val</span> fragmentRule <span class=\"token operator\">=</span> <span class=\"token function\">createRule</span><span class=\"token punctuation\">(</span>fragment<span class=\"token punctuation\">,</span> module <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">single</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">override</span> <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      fragmentViewModel\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n\n  <span class=\"token annotation builtin\">@Test</span>\n  <span class=\"token keyword\">fun</span> <span class=\"token function\">testBasicInvocation</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    onScreen<span class=\"token operator\">&lt;</span>EmailLoginForm<span class=\"token operator\">></span> <span class=\"token punctuation\">{</span>\n      emailField <span class=\"token punctuation\">{</span> <span class=\"token function\">typeText</span><span class=\"token punctuation\">(</span>EMAIL<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n      passwordField <span class=\"token punctuation\">{</span> <span class=\"token function\">typeText</span><span class=\"token punctuation\">(</span>PASSWORD<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n      loginButton<span class=\"token punctuation\">.</span><span class=\"token function\">click</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      verify <span class=\"token punctuation\">{</span>\n        fragmentViewModel<span class=\"token punctuation\">.</span><span class=\"token function\">loginWithCredentials</span><span class=\"token punctuation\">(</span>EMAIL<span class=\"token punctuation\">,</span> PASSWORD<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">class</span> EmailLoginForm<span class=\"token operator\">:</span> Screen<span class=\"token operator\">&lt;</span>EmailLoginForm<span class=\"token operator\">></span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">val</span> emailField <span class=\"token operator\">=</span> KEditText <span class=\"token punctuation\">{</span> <span class=\"token function\">withId</span><span class=\"token punctuation\">(</span>R<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">.</span>textFieldEmail<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">val</span> passwordField <span class=\"token operator\">=</span> KEditText <span class=\"token punctuation\">{</span> <span class=\"token function\">withId</span><span class=\"token punctuation\">(</span>R<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">.</span>textFieldPassword<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">val</span> loginButton <span class=\"token operator\">=</span> KButton <span class=\"token punctuation\">{</span> <span class=\"token function\">withId</span><span class=\"token punctuation\">(</span>R<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">.</span>buttonLogin<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">private</span> <span class=\"token keyword\">const</span> <span class=\"token keyword\">val</span> EMAIL <span class=\"token operator\">=</span> <span class=\"token string\">\"some@email.com\"</span>\n<span class=\"token keyword\">private</span> <span class=\"token keyword\">const</span> <span class=\"token keyword\">val</span> PASSWORD <span class=\"token operator\">=</span> <span class=\"token string\">\"password\"</span></code></pre></div>\n<p>Here we are using <a href=\"http://github.com/agoda-com/Kakao/\">Kakao</a>, it’s a nice tool to simplify working with Espresso tests. It provides implementation of <a href=\"https://martinfowler.com/bliki/PageObject.html\">Page Object pattern</a> and allows you to abstract interactions with your UI behind the abstract <a href=\"https://github.com/agoda-com/Kakao/blob/master/kakao/src/main/kotlin/com/agoda/kakao/screen/Screen.kt\">Screen</a> objects. Using Kakao you can improve maintainability of your tests, so if you are not using it yet, give it a try. Also we are using <a href=\"https://mockk.io/\">Mockk</a> for mocking, which uses all the power Kotlin gives us.</p>\n<p>That’s how with Koin, Kakao and Mockk you could easily test your fragments in isolation, making your life easier.</p>\n<p>You can check the source code for the sample <a href=\"https://github.com/olegosipenko/KoinTestApp\">here</a>.</p>","fields":{"slug":"/testing-isolated-fragments-with-koin/","tags":["android","koin","kakao","mockk","espresso","android fragments"]}}},{"node":{"id":"800a446b-0861-54ed-a2e3-a36e545abef1","frontmatter":{"category":"Coding","title":"The concept of SubForms - with React and Formik","date":"2019-07-02","summary":"Create forms at scale with Formik and Yup","thumbnail":{"relativePath":"pages/the-concept-of-subforms-with-formik/thumbnail.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAAsSAAALEgHS3X78AAABcklEQVQ4y51UzcqCQBSdN+st3AluXOTel6htL2FBuDDaBFGRZGSEuOiHoKI2RbXsR/N83AFjkMbsuzCMjHfOnHvOnWHIRJIk71k2xLxssE+LsmSK1+uVC8pkYLTxdrvh8XjwOf3+dqgU8H6/o9PpYDAYwPd9TCYTuK6L6XSaCyoFfD6fsCwL3W4Xi8UC8/kc2+2Wg8dx/DsgMWw0GqjX6+j3+2i1WhiPx/8vmRjato3hcIjdbof9fs+Zinm5DLPOkQnNZpOzdBwHYRi+zcpzmmXZiQnX6xXL5RKbzYbrl2qXzRX3sE+aHA4HXC6XjxpFUYTj8SjVkokNS3E6naCqKi8zCAKsViveKqTlaDTi7VOpVNBut7nOUoYp4Hq9hmEYqNVqKJfLUBQF1WqVH6LrOkzThKZpKJVKOJ/P30umUkk3SiZDqFVIgtlsxtc9z0Ov1+P9mZYu6smK3mFZSDUUHUvbglxN2yQ76F8hl/OerSJP2R9ITMR6qwehxQAAAABJRU5ErkJggg==","width":395,"height":325,"src":"/static/631a33919834353b3dda8e8578592a5b/b3029/thumbnail.png","srcSet":"/static/631a33919834353b3dda8e8578592a5b/b3029/thumbnail.png 1x,\n/static/631a33919834353b3dda8e8578592a5b/8d141/thumbnail.png 1.5x,\n/static/631a33919834353b3dda8e8578592a5b/ee72c/thumbnail.png 2x"}}},"authorName":"Nicholas Peretti","authorDescription":"Software Engineer","authorAvatar":{"relativePath":"pages/the-concept-of-subforms-with-formik/avatar.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAMFBP/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAcKk+4zgAAf/xAAZEAEAAgMAAAAAAAAAAAAAAAACAQMQEiD/2gAIAQEAAQUCJlJVI4M6oXGs8f/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABsQAQACAgMAAAAAAAAAAAAAAAEAAhAgITFC/9oACAEBAAY/AgO2cmBlvTbX/8QAGxABAQACAwEAAAAAAAAAAAAAAREAIRAgQVH/2gAIAQEAAT8hBOpDNUohZx7hMll+40df/9oADAMBAAIAAwAAABBDwAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEBAAICAwAAAAAAAAAAAAABESFBADEQIFH/2gAIAQEAAT8QxBALK8VVkQLA7X54WBCyOzfKvBj0MduVz6//2Q==","width":50,"height":50,"src":"/static/9347eae31d09e05f032d02892f955d38/d2d31/avatar.jpg","srcSet":"/static/9347eae31d09e05f032d02892f955d38/d2d31/avatar.jpg 1x,\n/static/9347eae31d09e05f032d02892f955d38/0b804/avatar.jpg 1.5x,\n/static/9347eae31d09e05f032d02892f955d38/753c3/avatar.jpg 2x,\n/static/9347eae31d09e05f032d02892f955d38/31ca8/avatar.jpg 3x"}}},"headerImage":{"relativePath":"pages/the-concept-of-subforms-with-formik/headerImage.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsSAAALEgHS3X78AAAAUUlEQVQY06WOIQ4AMQgE+/8nYSoQaExFRQmSH4AovX7gkiM3djOZbecH7W2IiDGGqu69y7K7997NrFzOzLXWnFNEbrwm36vMjIgAQETl2194AJcvYFpZxM6mAAAAAElFTkSuQmCC","width":1280,"height":384,"src":"/static/8ce613d93c9ee2f1e3b248f2aabe8efc/26421/headerImage.png","srcSet":"/static/8ce613d93c9ee2f1e3b248f2aabe8efc/26421/headerImage.png 1x,\n/static/8ce613d93c9ee2f1e3b248f2aabe8efc/34a7a/headerImage.png 1.5x"}}}},"html":"<p>In the last few months I’ve been working a lot with forms. I had to do a large refactoring in one of AUTO1’s applications, and through all the research, I also encountered the term <strong>subform</strong>. The concept was troublesome not only for me.\nI found more than one issue on the Formik repository about developers asking for help.\nIn this article I'll try to clarify this concept and show you how to use it properly.</p>\n<h2>What the heck is a subform anyway?</h2>\n<p>If you’ve ever worked on a medium-large project with a reasonable amount of forms, you might have probably noticed that you could potentially reuse a lot of fields, sometimes even entire forms!\nThat’s the core of the subform concept: reusable components (fields or group of fields) that can be composed together to create bigger forms.</p>\n<p>At the beginning I had a lot of questions in my mind like:</p>\n<ul>\n<li>How can I handle validation?</li>\n<li>How can I handle form state?</li>\n<li>How can I stay flexible?</li>\n</ul>\n<p>These questions and many others appeared while I was refactoring existing codebase. Many similar questions created by other developers appeared in the Formik repository as issues.</p>\n<p>Don’t get me wrong: implementing scalable validation for a single form is not that hard. The complicated thing is to keep validation and state flexible while you write your subforms. What does it mean? We’ll see that in a moment.</p>\n<h2>How Formik can help</h2>\n<p>Formik is an amazing library, one of the bests for this job, and here’s what it brings to the table:</p>\n<h3>Auto-connected Field component</h3>\n<p>Formik provides a Field component that, thanks to the React Context API, will be automatically connected to the Form component that wraps our Field, regardless of how deep our Field is in the tree.</p>\n<h3>Yup validation schema</h3>\n<p>Yup is a library to create validation schemas. This library is very similar to the prop-types of React, so it is very simple to start using it.\nFormik supports Yup natively, so you just need to define the schema and pass it to Formik, it will take care of the rest.</p>\n<p>So this is how Formik will make our life easier not only while creating subforms but also when we’ll need to maintain them!</p>\n<h2>Enough talking, show me the code</h2>\n<p>Let’s create our first subform! Before we start, we need to clarify what <strong>our subform will be responsible</strong> for:</p>\n<ul>\n<li>Provide a basic validation schema</li>\n<li>Provide some default values (required by Formik)</li>\n<li>Provide the list of its fields (in case we need to access the data from outside, as we’ll see later)</li>\n<li>Provide a React component that will render the subform to the user and its fields’ errors</li>\n</ul>\n<p>In our case, we're going to create a form that allows to create a new user.\nWe'll need to display the following fields:</p>\n<ul>\n<li>First name</li>\n<li>Last name</li>\n<li>Email</li>\n<li>Password</li>\n</ul>\n<p>Just keep it simple. So, let’s create our <code class=\"language-text\">NewUserSubForm</code> directory and our <code class=\"language-text\">fieldsNames</code> file. It’s just a file that exports constants, don’t worry. It will look like this:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/fieldsNames.js</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">FIRST_NAME</span> <span class=\"token operator\">=</span> <span class=\"token string\">'firstName'</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">LAST_NAME</span> <span class=\"token operator\">=</span> <span class=\"token string\">'lastName'</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">EMAIL</span> <span class=\"token operator\">=</span> <span class=\"token string\">'email'</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token operator\">=</span> <span class=\"token string\">'password'</span></code></pre></div>\n<h3>Defining the validation schema</h3>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/validationSchema.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">as</span> yup <span class=\"token keyword\">from</span> <span class=\"token string\">'yup'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">MIN_PASSWORD_LENGTH</span> <span class=\"token operator\">=</span> <span class=\"token number\">8</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">REQUIRED_MESSAGE</span> <span class=\"token operator\">=</span> <span class=\"token string\">'This field is required'</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">INVALID_EMAIL_FORMAT</span> <span class=\"token operator\">=</span> <span class=\"token string\">'Invalid email format'</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">PASSWORD_TOO_SHOWRT</span> <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">The password must be at least </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">MIN_PASSWORD_LENGTH</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> characters long</span><span class=\"token template-punctuation string\">`</span></span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup\n    <span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">email</span><span class=\"token punctuation\">(</span><span class=\"token constant\">INVALID_EMAIL_FORMAT</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup\n    <span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">.</span><span class=\"token function\">min</span><span class=\"token punctuation\">(</span><span class=\"token constant\">MIN_PASSWORD_LENGTH</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD_TOO_SHOWRT</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>We’ve just defined our validation schema regardless the markup of our form. This file just contains all the validation logic and has one responsibility. If in the future we’ll need to add some more validation options, we’ll just need to change it here.</p>\n<p>Now it’s time for the default values. Initial values are <strong>required</strong> from Formik because it uses controlled inputs. So, if you don’t specify those values, you’ll get and error from React as soon as you try to change the content of the input.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/defaultValues.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token string\">''</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3>Rendering the subform</h3>\n<p>And now the master piece: The React component. Remember: <strong>we just need to use the Fields and not the Formik or the Form components</strong>.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/index.js</span>\n<span class=\"token keyword\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> Fragment <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Field<span class=\"token punctuation\">,</span> ErrorMessage <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'formik'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">NewUserSubForm</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>Fragment<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>Fragment<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And that’s it. In this phase we can test every single part of our subform: validation, the default values schema and the React component.</p>\n<p><strong>A piece of advice</strong>: Formik sets the fields’ values in its state using the <code class=\"language-text\">name</code> property, but the cool thing is that it uses it like the Lodash <code class=\"language-text\">set</code> function. It means that we can write the name of a field like this: <code class=\"language-text\">user.firstName</code>. In this way Formik will create an object in its state called <code class=\"language-text\">user</code>, and then a property inside of <code class=\"language-text\">user</code> called <code class=\"language-text\">firstName</code> that will contain the value of our field.</p>\n<p>This mechanism gives us power to improve the flexibility of our subform. How?</p>\n<h3>Making a subform flexible</h3>\n<p>Let’s edit our component in a way that it will accept an optional property called <code class=\"language-text\">namespace</code>. If received, the component will prepend the namespace to every field name. In this way it will be easier to wrap all the subform’s values under a certain object in the main form.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/index.js</span>\n<span class=\"token keyword\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> Fragment <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> PropTypes <span class=\"token keyword\">from</span> <span class=\"token string\">'prop-types'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Field<span class=\"token punctuation\">,</span> ErrorMessage <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'formik'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">NewUserSubForm</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">static</span> propTypes <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    namespace<span class=\"token operator\">:</span> PropTypes<span class=\"token punctuation\">.</span>string<span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">fieldName</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> namespace <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props\n\n    <span class=\"token keyword\">return</span> namespace <span class=\"token operator\">?</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>namespace<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">.</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>fieldName<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span> <span class=\"token operator\">:</span> fieldName\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> withNamespace <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span>\n\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>Fragment<span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>Field component<span class=\"token operator\">=</span><span class=\"token string\">\"input\"</span> name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n        <span class=\"token operator\">&lt;</span>ErrorMessage name<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token function\">withNamespace</span><span class=\"token punctuation\">(</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>Fragment<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>We don’t need to do that with the other parts of the subform, the main form will be responsible for that. And, about the main form, let’s see how to implement it!</p>\n<h2>The main form</h2>\n<p>Finally, we’re going to create our main form component. Let’s define its responsibilities just like we did with our subform. The main form will be responsible for:</p>\n<ul>\n<li>Compose the validation</li>\n<li>Compose the React components</li>\n<li>Compose and eventually overwrite the default values</li>\n<li>Orchestrate all the above elements in the right way (if we add a namespace for a subform we should put its validation schema under the same namespace)</li>\n<li>Handle the submission of the form</li>\n<li>Handle the display logic of the server-side errors (and all the form level errors)</li>\n</ul>\n<p>It's a lot of responsibilities, <em>and that’s all right</em>. The main form represents a specific point in the UI/UX where the user needs to insert some data. In our case, it could be a registration form, but it could also be a registration combined with a purchase, just like when you buy something from amazon and you agree to sign up in the process.</p>\n<p>The point is: <strong>A Form is a unique component that represent a specific use case</strong>, so it has to be designed accordingly. That’s why it makes no sense to create a “god-form” component with hundreds of props that decides which endpoint the form is going to use. It just creates useless complexity.</p>\n<p>In my opinion, the best way to organize this approach is to create a folder where you’ll store all your subforms. Every subform will be represented by its directory and it will contain all its parts: validation, values, fields and the React component.\nA main form, instead, should be created ad-hoc to fit the needs of a certain use case, for example inside a certain route.</p>\n<p>So, with that in mind, let’s proceed to the implementation. We’ll have our directory called <code class=\"language-text\">registrationForm</code> and it will have the same parts of a subform:</p>\n<p>Fields Names</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  CreateNewUserRoute/form/fieldsNames.js</span>\n<span class=\"token keyword\">export</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./subforms/NewUserSubForm/fieldsNames'</span>\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token constant\">USER</span> <span class=\"token operator\">=</span> <span class=\"token string\">'user'</span></code></pre></div>\n<p>Validation</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  CreateNewUserRoute/form/validationSchema.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">as</span> yup <span class=\"token keyword\">from</span> <span class=\"token string\">'yup'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">USER</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n<span class=\"token keyword\">import</span> userValidationSchema <span class=\"token keyword\">from</span> <span class=\"token string\">'./subforms/NewUserSubForm/validationSchema'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">USER</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> userValidationSchema<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Default values</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  CreateNewUserRoute/form/defaultValues.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">USER</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./field Names'</span>\n<span class=\"token keyword\">import</span> userDefaultValues <span class=\"token keyword\">from</span> <span class=\"token string\">'./subforms/NewUserSubForm/defaultValues'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token punctuation\">[</span><span class=\"token constant\">USER</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> userDefaultValues<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>The React component</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  CreateNewUserRoute/form/index.js</span>\n<span class=\"token keyword\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Formik<span class=\"token punctuation\">,</span> Form <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'formik'</span>\n<span class=\"token keyword\">import</span> NewUserSubForm <span class=\"token keyword\">from</span> <span class=\"token string\">'./subforms/NewUserSubForm'</span>\n<span class=\"token keyword\">import</span> validationSchema <span class=\"token keyword\">from</span> <span class=\"token string\">'./validationSchema'</span>\n<span class=\"token keyword\">import</span> defaultValues <span class=\"token keyword\">from</span> <span class=\"token string\">'./defaultValues'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">USER</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n<span class=\"token keyword\">import</span> ErrorBanner <span class=\"token keyword\">from</span> <span class=\"token string\">'path/to/components/ErrorBanner'</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">NewUserSubForm</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    unknownErrors<span class=\"token operator\">:</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function-variable function\">onSubmit</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">async</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">values<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> setSubmitting<span class=\"token punctuation\">,</span> setErrors <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">//  Send values somehow</span>\n      <span class=\"token keyword\">await</span> <span class=\"token function\">sendForm</span><span class=\"token punctuation\">(</span>values<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">//  Map and show the errors in your form</span>\n      <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>formErrors<span class=\"token punctuation\">,</span> unknownErrors<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">mapErrorsFromRequest</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">)</span>\n\n      <span class=\"token function\">setErrors</span><span class=\"token punctuation\">(</span>formErrors<span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n        unknownErrors<span class=\"token punctuation\">,</span>\n      <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">finally</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">setSubmitting</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> unknownErrors <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state\n\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token operator\">&lt;</span>Formik onSubmit<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>onSubmit<span class=\"token punctuation\">}</span> initialValues<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>defaultValues<span class=\"token punctuation\">}</span> validationSchema<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>validationSchema<span class=\"token punctuation\">}</span><span class=\"token operator\">></span>\n        <span class=\"token punctuation\">{</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>\n          <span class=\"token operator\">&lt;</span>Form<span class=\"token operator\">></span>\n            <span class=\"token punctuation\">{</span>unknownErrors <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">&lt;</span>ErrorBanner errors<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span>unknownErrors<span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span><span class=\"token punctuation\">}</span>\n            <span class=\"token operator\">&lt;</span>NewUserSubForm namespace<span class=\"token operator\">=</span><span class=\"token punctuation\">{</span><span class=\"token constant\">USER</span><span class=\"token punctuation\">}</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n          <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>Form<span class=\"token operator\">></span>\n        <span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span>\n      <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>Formik<span class=\"token operator\">></span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>And that’s it! Of course, this is a very simple example, you could have different needs.</p>\n<h2>Helpful advices on creating subforms</h2>\n<p>I want to leave you with some advices that helped me while I was refactoring my codebase. It's good to have them in mind to ease the process of code refactoring.</p>\n<h3>A subform should have only first level values in its state</h3>\n<p>A subform should have only first level values in its state, which means that, when you design a subform, you shouldn’t get crazy about the shape of its values. It should be a flat object and every key should contain the field value.\nThis way it’s so much easier to write validations, default values and error handling (and why not, also the React component).</p>\n<p>You can avoid this advice <strong>only when you are using a subform into you subform</strong>. For example, let’s say you have an address subform. It has a lot of fields and a complex validation schema. In that scenario all the logic will be handled by the address subform and you’ll just need to orchestrate it in your own subform, just like you would do in the main form.</p>\n<h3>Keep the validation schema extensible and scalable</h3>\n<p>I didn’t do it in this article but the idea is to export a function instead of a schema. This function will accept parameters that will define the schema that you’ll get.\nIn this case you can toggle the “required” validation in some cases, or other kinds of validation.</p>\n<p><strong>Example</strong>: let’s say that we want to make the “lastName” field optional, but not always. That’s how you could define your schema:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">//  UserSubform/validationSchema.js</span>\n<span class=\"token keyword\">import</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">as</span> yup <span class=\"token keyword\">from</span> <span class=\"token string\">'yup'</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> <span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD</span> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'./fieldsNames'</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">MIN_PASSWORD_LENGTH</span> <span class=\"token operator\">=</span> <span class=\"token number\">8</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">REQUIRED_MESSAGE</span> <span class=\"token operator\">=</span> <span class=\"token string\">'This field is required'</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">INVALID_EMAIL_FORMAT</span> <span class=\"token operator\">=</span> <span class=\"token string\">'Invalid email format'</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">PASSWORD_TOO_SHOWRT</span> <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">The password must be long at least </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">MIN_PASSWORD_LENGTH</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> characters</span><span class=\"token template-punctuation string\">`</span></span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">function</span> <span class=\"token function\">validationSchema</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">mandatoryFields <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">[</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">object</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n    <span class=\"token punctuation\">[</span><span class=\"token constant\">FIRST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token constant\">LAST_NAME</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">lazy</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>mandatoryFields<span class=\"token punctuation\">.</span>lastName <span class=\"token operator\">?</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span> yup<span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token constant\">EMAIL</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup\n      <span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">email</span><span class=\"token punctuation\">(</span><span class=\"token constant\">INVALID_EMAIL_FORMAT</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token constant\">PASSWORD</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span> yup\n      <span class=\"token punctuation\">.</span><span class=\"token function\">string</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">required</span><span class=\"token punctuation\">(</span><span class=\"token constant\">REQUIRED_MESSAGE</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">.</span><span class=\"token function\">min</span><span class=\"token punctuation\">(</span><span class=\"token constant\">MIN_PASSWORD_LENGTH</span><span class=\"token punctuation\">,</span> <span class=\"token constant\">PASSWORD_TOO_SHOWRT</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Now you have a scalable validation schema.\nIn this way you can always decide if a certain field is required or not. Also, you can extend that function to add parameters. In this way, if your subform scales, you’ll just need to add parameters and adjust the code in the subform accordingly, but <strong>every single form that uses your subform won’t be affected by these changes because everything is retro compatible</strong>.</p>\n<h2>Conclusions</h2>\n<p>Dealing with forms is not easy. Of course, there are simple cases, but there are also trickier ones. This was my way to organize the code, and of course, it’s not perfect.\nI’m sure there are other thousands amazing ways to solve this problem better than this, but for now, this is the best way I’ve found to keep everything testable, maintainable and scalable.</p>\n<p>I hope this will help you, and if you have a better approach, I’m looking forward to reading it!\nUntil next time, happy hacking!</p>","fields":{"slug":"/the-concept-of-subforms-with-formik/","tags":["formik","forms","react","subforms"]}}},{"node":{"id":"61712d64-9fb5-5c05-8e36-ae37d9bf956d","frontmatter":{"category":"Coding","title":"Take a deep Bref, and run your Symfony app serverless","date":"2019-06-24","summary":"Yet another case study of developing serverless apps with PHP.","thumbnail":{"relativePath":"pages/php-serverless-with-bref/blog.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABAACA//EABUBAQEAAAAAAAAAAAAAAAAAAAAC/9oADAMBAAIQAxAAAAFvIGahEOP/xAAYEAADAQEAAAAAAAAAAAAAAAAAARMCEv/aAAgBAQABBQLlG9clCrRTXVWf/8QAFREBAQAAAAAAAAAAAAAAAAAAEBH/2gAIAQMBAT8Bh//EABURAQEAAAAAAAAAAAAAAAAAAAAR/9oACAECAQE/Aar/xAAXEAADAQAAAAAAAAAAAAAAAAAAESAh/9oACAEBAAY/AsFP/8QAGRABAQEBAQEAAAAAAAAAAAAAAREAMSFx/9oACAEBAAE/IROt9TIugIGZBbfeZrv/2gAMAwEAAgADAAAAEC//AP/EABcRAAMBAAAAAAAAAAAAAAAAAAABESH/2gAIAQMBAT8Q0qiI/8QAFhEBAQEAAAAAAAAAAAAAAAAAAREQ/9oACAECAQE/ECGLn//EAB4QAQEAAQMFAAAAAAAAAAAAAAERACExUUFhgcHR/9oACAEBAAE/EG97q6XxipRA8SmUKC93GIysvGBJkuwRxavr5n//2Q==","width":488,"height":325,"src":"/static/af9a71b099ce7da56586de41ed112b03/a2998/blog.jpeg","srcSet":"/static/af9a71b099ce7da56586de41ed112b03/a2998/blog.jpeg 1x"}}},"authorName":"Wojciech Oroński","authorDescription":"Wojciech is a Senior Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/php-serverless-with-bref/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACtklEQVQ4y4VUvWtTURS/SV7sUIeK+g/o6GSS9/Ly8pKmKc0g2gqBVkrBQAcpOggOuhVxcbAG/FpcOgqOguAg1G6COIifCKKIijo5qDWf/n4v57QHFx/8uOfde+7vnm9Xq8WZqalKmmupVNzl5Mvn81WgncvlXmHtAh3IH7CuA7NhONKNojBbrUbbHI7C5GSc4YEQFYGNQqEw9H1/CHkohD3K3JP950CTd0gUxyWvXq+kkx9DtqyXhGBLiQnKtJQwD17l3Xq9mq5UooxTN0lmLOooMdx8B/k+cA94RiJD3AuCgPJ1cpTLJc8ZN617JPqD9UwQ+OMaV3jiYe8I8ElI6UVXSJedScCGWJe8KvIpns3M1NLlcpgl4JIn+hEe7IsBPZLj/zPWvUk25bW+gIdffL+wZ3FxLsX4Ms4EY2RCtGli3RErz/KgLQd0tS/kL+Hq7lar6UiihAQtFcI75p569dDBmjdilbXwG4j38WIcRx5Ki3WWYXkZtx+phdAfyL0fTpMADMxLt0dkJY8kUvyZf0rstAnVQEmdEClhVwgv81IYBmMsVnWXTYAOGRPCEyaGO4QQPoq5AyWH/BPrIW0tbSu6u7R0PAWicei81tIxLv/mS+smuENTV3d33C4n1pkMnxedri0drI95OGuDK6+pQkutNNnNQ+eX8Wpoyuai49SA8MJU/kALXPZCEs3PH03hfz9Ivsr+FhNi3GWYDmqnNK3bfK1YLPJ/k/W4sHAsZbJ7g2fUUWKx7pL2pyquCcl74CZwDt0ywTPGDshqt8hUagNP5c6DRqOWZps6DsdkMI5Ib8lQOOn+87Fl2aKcA5qsZNowe8wkV1FcYfqB75CvAXP50XcYaDDwOHsrybiyurqy7SlnYjJgWbx0RTOJ2ExA+QLwRDOqWZVWXQMOUHd6upqmZSQj119HCq8aFJGDXQAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/d606e0fe3a0b15d5494a19629b2b3022/45876/avatar.png","srcSet":"/static/d606e0fe3a0b15d5494a19629b2b3022/45876/avatar.png 1x"}}},"headerImage":null},"html":"<h2>tl;dr</h2>\n<p>Since AWS lambda supports custom runtimes you can use PHP to create AWS lambda functions.\nBut it comes with two major drawbacks </p>\n<ul>\n<li>first running custom runtime for PHP is not very easy,</li>\n<li>the second which is limiting usage of popular PHP frameworks in lambda functions development process.</li>\n</ul>\n<p>With bref.sh these problems will disappear. Let's try to run Symfony framework as a serverless app.</p>\n<h2>What is serverless ?</h2>\n<p>What does it mean that something is Serverless? Does it mean there are no servers at all?\nOf course not. There are still servers behind scenes, but you don't have to worry about maintaining the servers and reserve their capacity. Your infrastructure is scaled automatically, and you just pay only for what you use.\nDoes this kind of architecture have only pros or there are some drawbacks?\nLet's leave the discussion of all the smaller pros and cons of serverless applications for another article.\nI will focus on the biggest drawback which is an impact on our code. Frameworks that we use in our daily PHP development are not ready to work with lambdas because they were not designed for those kinds of architecture.\nImagine you are a PHP developer and you want to run serverless microservice using one of the most popular frameworks like Symfony or Laravel. Imagine you can develop your microservice locally and just deploy it as lambda functions. Is it possible with PHP\nprogramming language? Yes, it is. Even if AWS Lambda does not have native support for PHP.</p>\n<h2>Here comes Bref.</h2>\n<p>Since AWS lambda supports custom runtimes, you can create one for PHP and run your lambda functions written in that language. There are plenty of articles which describe the process of creating custom runtimes, but believe me it's time-consuming and not super easy.\nLet's take a look at the bref.sh project and try to run a simple Symfony app as lambda.</p>\n<p>I assume you have knowledge about Symfony framework, or you have an existing project and some knowledge about AWS platform.</p>\n<p>Before we start please make sure you have installed:</p>\n<ul>\n<li><a href=\"https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html\">AWS CLI</a></li>\n<li><a href=\"https://aws.amazon.com/serverless/sam/\">AWS SAM CLI</a></li>\n<li>And setup AWS credentials</li>\n</ul>\n<p>First, we have to add Bref to our project with <code class=\"language-text\">composer require mnapoli/bref</code>\nThen from your project root command line run <code class=\"language-text\">vendor/bin/bref init</code>\nIt will create two additional files in your project template.yaml and index.php.\nYou can remove index.php for this moment, as it will be unnecessary.</p>\n<p>As you may know, AWS lambda filesystem is read-only excluding <code class=\"language-text\">/tmp</code> dir\nSo we have to extend <code class=\"language-text\">src/Kernel.php</code> of Symfony with these two functions</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\">    public function getLogDir(): string\n    {\n        // When on the lambda only /tmp is writeable\n        if (getenv('LAMBDA_TASK_ROOT') !== false) {\n            return '/tmp/log/';\n        }\n\n        return $this->getProjectDir().'/var/log';\n    }\n\n    public function getCacheDir(): string\n    {\n        // When on the lambda only /tmp is writeable\n        if (getenv('LAMBDA_TASK_ROOT') !== false) {\n            return '/tmp/cache/'.$this->environment;\n        }\n\n        return $this->getProjectDir().'/var/cache/'.$this->environment;\n    }</code></pre></div>\n<p>Let's take a closer look at template.yaml</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">Resources</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">Website</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">Type</span><span class=\"token punctuation\">:</span> AWS<span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span>Serverless<span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span>Function\n        <span class=\"token key atrule\">Properties</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">FunctionName</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'symfony-website'</span>\n            <span class=\"token key atrule\">CodeUri</span><span class=\"token punctuation\">:</span> .\n            <span class=\"token key atrule\">Handler</span><span class=\"token punctuation\">:</span> public/index.php\n            <span class=\"token key atrule\">Timeout</span><span class=\"token punctuation\">:</span> <span class=\"token number\">30</span> <span class=\"token comment\"># in seconds (API Gateway has a timeout of 30 seconds)</span>\n            <span class=\"token key atrule\">MemorySize</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1024</span>\n            <span class=\"token key atrule\">Runtime</span><span class=\"token punctuation\">:</span> provided\n            <span class=\"token key atrule\">Layers</span><span class=\"token punctuation\">:</span>\n                <span class=\"token punctuation\">-</span> <span class=\"token string\">'arn:aws:lambda:us-east-1:209497400698:layer:php-73-fpm:1'</span>\n            <span class=\"token key atrule\">Events</span><span class=\"token punctuation\">:</span>\n                <span class=\"token key atrule\">HttpRoot</span><span class=\"token punctuation\">:</span>\n                    <span class=\"token key atrule\">Type</span><span class=\"token punctuation\">:</span> Api\n                    <span class=\"token key atrule\">Properties</span><span class=\"token punctuation\">:</span>\n                        <span class=\"token key atrule\">Path</span><span class=\"token punctuation\">:</span> /\n                        <span class=\"token key atrule\">Method</span><span class=\"token punctuation\">:</span> ANY\n                <span class=\"token key atrule\">HttpSubPaths</span><span class=\"token punctuation\">:</span>\n                    <span class=\"token key atrule\">Type</span><span class=\"token punctuation\">:</span> Api\n                    <span class=\"token key atrule\">Properties</span><span class=\"token punctuation\">:</span>\n                        <span class=\"token key atrule\">Path</span><span class=\"token punctuation\">:</span> /<span class=\"token punctuation\">{</span>proxy+<span class=\"token punctuation\">}</span>\n                        <span class=\"token key atrule\">Method</span><span class=\"token punctuation\">:</span> ANY\n\n    <span class=\"token key atrule\">Console</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">Type</span><span class=\"token punctuation\">:</span> AWS<span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span>Serverless<span class=\"token punctuation\">:</span><span class=\"token punctuation\">:</span>Function\n        <span class=\"token key atrule\">Properties</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">FunctionName</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'symfony-console'</span>\n            <span class=\"token key atrule\">CodeUri</span><span class=\"token punctuation\">:</span> .\n            <span class=\"token key atrule\">Handler</span><span class=\"token punctuation\">:</span> bin/console\n            <span class=\"token key atrule\">Timeout</span><span class=\"token punctuation\">:</span> <span class=\"token number\">120</span> <span class=\"token comment\"># in seconds</span>\n            <span class=\"token key atrule\">Runtime</span><span class=\"token punctuation\">:</span> provided\n            <span class=\"token key atrule\">Layers</span><span class=\"token punctuation\">:</span>\n                <span class=\"token punctuation\">-</span> <span class=\"token string\">'arn:aws:lambda:us-east-1:209497400698:layer:php-73:1'</span> <span class=\"token comment\"># PHP</span>\n                <span class=\"token punctuation\">-</span> <span class=\"token string\">'arn:aws:lambda:us-east-1:209497400698:layer:console:1'</span> <span class=\"token comment\"># The \"console\" layer</span></code></pre></div>\n<p>Thanks to the configuration stored in template.yaml, Bref will create CloudFormation with two most important resources which are lambda functions that will handle all the requests. One called symfony-website and the second symfony-console, both names are defined under <code class=\"language-text\">FunctionName</code> key.\nTheir execution will be available thanks to API Gateway which also will be created during the deploy process.\nFor testing purpose, you don't have to change template file much. Please remember to check your AWS default region if it's different than <code class=\"language-text\">us-east-1</code> just change it in all <code class=\"language-text\">Layers</code> key of your Resources.</p>\n<p>OK. Let's check how it works and deploy.\nFirst, we need to create s3 bucket per our app with simple AWS CLI command <code class=\"language-text\">aws s3 mb s3://&lt;bucket-name></code>\nThen upload the code and generate the stack configuration:</p>\n<div class=\"gatsby-highlight\" data-language=\"shell\"><pre class=\"language-shell\"><code class=\"language-shell\">sam package \\\n    --output-template-file .stack.yaml \\\n    --s3-bucket &lt;bucket-name&gt;</code></pre></div>\n<p>Finnaly deploy our microservice: </p>\n<div class=\"gatsby-highlight\" data-language=\"shell\"><pre class=\"language-shell\"><code class=\"language-shell\">sam deploy \\\n    --template-file .stack.yaml \\\n    --capabilities CAPABILITY_IAM \\\n    --stack-name &lt;stack-name&gt;</code></pre></div>\n<p>After we receive output \"Successfully created/updated stack - <stack-name>\" our serverless microservice is ready to use.\nLet's check our resources in the AWS console. SAM deploy created the corresponding AWS Lambda Functions and API Gateway resources.</p>\n<p>Lambda Functions:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/9f965078bf4cd620f90ecee4869716fd/7f308/aws-lambda.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 50.13648771610555%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAABNUlEQVQoz61Sy07DMBDs/x/4Ar6AX+DGjV8AIaRKtFWdOH7GiZN0mN2qKCqUUw8j7+6MZ3edbKwPOFoHay0655BSQozxX4QQ9FRt18A3BwR71PrGh4i37Rc+dwfYvsCVEV0/3ITNBTsO0MQMk0fY1yfE5weEl0c13Xh2ed8bfBwMtq3DPmS0NG17olQ0q1NRzpCaaI33qCUjxwAvE0YaptzDtBZH0yAmkqWgozDEhH4Y4CjMnF7ilDNzrstcdKKR2lgrxEsN53mGz7yYCpZlUYzjiImiE2N5q8ymUp+mSd9P6jNjz28wsNHptKixGg68bGOBCT0K40qjSnGt07kzp3BykZxAcuUYyzcQQ9GroewtcFxR1rzkawjnVpy74tZaNQzyK9wJP4aXDn+Jrrlb8S/De0z4DT/9/7PjufbWAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"lambda\"\n        title=\"Lambda\"\n        src=\"/static/9f965078bf4cd620f90ecee4869716fd/40fad/aws-lambda.png\"\n        srcset=\"/static/9f965078bf4cd620f90ecee4869716fd/707e9/aws-lambda.png 148w,\n/static/9f965078bf4cd620f90ecee4869716fd/649e0/aws-lambda.png 295w,\n/static/9f965078bf4cd620f90ecee4869716fd/40fad/aws-lambda.png 590w,\n/static/9f965078bf4cd620f90ecee4869716fd/b3fef/aws-lambda.png 885w,\n/static/9f965078bf4cd620f90ecee4869716fd/7f308/aws-lambda.png 1099w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>API Gateway:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/8fe03eca82db3f2292591c6c2d95aac2/a7e37/aws-api.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 45.95782073813708%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA0klEQVQoz61SUarCMBDM/a/lxxO8Q3mCWkvbxE1Fk22zY1ONWqso6MD8LDuzMyGKbAN7cChqwjrfwhQ5inWFAzm4hnt6HK0HuxYiMmEIARHOOTAzVFkb5BRQ7gXkgTKzWC1KLOcF/v+2A7PZBlVGg/CZaWSCMsZA+iMyXBJ0XQttNPbNDm3H10XBWPiIZDwYpkG4VGBuwd735t2oWjJ8lXJieP8mz4T3s1dQWuuJOOGclkcH3uGaMIpDuFU7p5VR7U+oouCXUFVVI/5FIovdhfQFT8GXwnE+CMQGAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"api-gateway\"\n        title=\"API Gateway\"\n        src=\"/static/8fe03eca82db3f2292591c6c2d95aac2/40fad/aws-api.png\"\n        srcset=\"/static/8fe03eca82db3f2292591c6c2d95aac2/707e9/aws-api.png 148w,\n/static/8fe03eca82db3f2292591c6c2d95aac2/649e0/aws-api.png 295w,\n/static/8fe03eca82db3f2292591c6c2d95aac2/40fad/aws-api.png 590w,\n/static/8fe03eca82db3f2292591c6c2d95aac2/b3fef/aws-api.png 885w,\n/static/8fe03eca82db3f2292591c6c2d95aac2/a7e37/aws-api.png 1138w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Just check your execution url in API Gateway:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/e34b8df67c48bf1b913344107d7bda18/2e35f/aws-api-invoke.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 72.31833910034602%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB7klEQVQ4y4WSeU/bQBDF8/0/TUtIgECpFNTwb9MmqFCphwiub8fnenftvM6M4zQHoiv9NN5r/N7sDIJUYV0aYNOiMg2ec4tVbvBSdHFV9PMG88cE9/MQs0WOT19L3H0pcL8shdmCIjEAjc1mwwHaaLieAyeI8PuPj2cvxM8XFys/wi/Hw/cfHh4ePSy+ufi8dLB8CrCg+fzBkbh89DGQZASnbJsGVZFhncRQVYXGGuhawehaorUaTUPYGtbUdF7TXkXfStYYSdgrbNsWxhghzzJEYQitNd4a1jZot/d5HFhuSGHg+1g5ruC4PuJ1hiTNUJYFiqJAnvcxl1iW5UE8SMgK67qG0hZJVsINYiEv690+wz9m5Lv9982cJNwfhh4pjkKqZ4k0TUXB8ZnjcZJQKUXyK1HKNtZsVxmpZX+ur/trnNQwSRIEQYA4juF5Ljw/IMuKG4HstTtrzH8THtux1orNLEuhzIYa/227Ynm/bVhhp8wTpWyfkYeivuQS9Cha43uiluOWwX523mRVDCfPqBdD6sUoimQuPSr7RuavKmzbza4enIj7q6YH0HS5e6BOkdbdw+zDygVqM7Vl8HE6wy3Rx/HkFu+GlxheXGM4vsbo8gajqw84v7iRtbPRBGfjDjlD6+eTKd5fTTGc3OEvcF4zJwFgXgwAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"aws-api-invoke\"\n        title=\"API Gateway invoke url\"\n        src=\"/static/e34b8df67c48bf1b913344107d7bda18/40fad/aws-api-invoke.png\"\n        srcset=\"/static/e34b8df67c48bf1b913344107d7bda18/707e9/aws-api-invoke.png 148w,\n/static/e34b8df67c48bf1b913344107d7bda18/649e0/aws-api-invoke.png 295w,\n/static/e34b8df67c48bf1b913344107d7bda18/40fad/aws-api-invoke.png 590w,\n/static/e34b8df67c48bf1b913344107d7bda18/b3fef/aws-api-invoke.png 885w,\n/static/e34b8df67c48bf1b913344107d7bda18/2e35f/aws-api-invoke.png 1156w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Then run it in your browser. You should see symfony default page.</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/6f5d7e9de050b02b7ca242f43134d64a/0f040/symfony.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 64.08333333333334%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAABYlAAAWJQFJUiTwAAABvklEQVQ4y51Ty3LiMBDk//9gvyG58At74pYEiI2BFNjYhlrwS37bsnvVUrwkl60kU9XVo7E06pmRZ3Ec4xZFuF6vOJ/POJ1OYKxpmi+hbVtUVYXNZoMgCDAryxJ932McR0gptU9w43fA5HVdY8bDaZpiv98jDEN9CxX+xChoRmWO4+Dx8QEPCvP5HIvFAp7nwXVdsAIa9/0PNIrTCpMkwfPTErbt6OTb7RaXy0UrZilfNZ1wOtCPObqhRNt0KIpCt6GsSu0nSQqRZRBC6Dj9SA2S6zzPMQzDB4WdhKj+4Pf6F7LiCmezVWqfFJ6xXq9hWRaWy5VSb8O2bKxWK1ivr5o5WbblU8ld26myaohcgMmpiFPjrbLn1KXxVcOlnPgeI7/nu/eQU315WeJwOKj+7b7VN2MfFXad7gWl+77/b7ru0UUY+Dh5ZxyPg3rwEm/7XvPxILHb9fBcEwt8eU/I8mjDMIK9NWzAUhjjFoLCJ64rw1PMvMOBU2bPYvXKI4MmUr/STftNE2vUzQ1Ny/VN+63yJ0zfyF0nMKuqDHkRIssCAxEgzXztC2GQvscZ4zeRh3otRKieka9ZCB+VEvEXRYzl11Ft7fsAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"symfony\"\n        title=\"Symfony\"\n        src=\"/static/6f5d7e9de050b02b7ca242f43134d64a/40fad/symfony.png\"\n        srcset=\"/static/6f5d7e9de050b02b7ca242f43134d64a/707e9/symfony.png 148w,\n/static/6f5d7e9de050b02b7ca242f43134d64a/649e0/symfony.png 295w,\n/static/6f5d7e9de050b02b7ca242f43134d64a/40fad/symfony.png 590w,\n/static/6f5d7e9de050b02b7ca242f43134d64a/b3fef/symfony.png 885w,\n/static/6f5d7e9de050b02b7ca242f43134d64a/301c0/symfony.png 1180w,\n/static/6f5d7e9de050b02b7ca242f43134d64a/0f040/symfony.png 1200w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<p>Performance:</p>\n<ul>\n<li>PHP Performance on Lambda isn't super-hot. During my tests, I achieved ~40ms for a simple CRUD POST request with 2048 MB of the memory set.</li>\n</ul>\n<p>Other drawbacks:</p>\n<ul>\n<li>While using MySQL or PqSql cold starts (around 5s)</li>\n<li>Bref is a young project in advanced beta stage.</li>\n<li>Still, it's a unicorn and only AWS is supported</li>\n<li>Not all PHP extensions are working out of the box, but almost every extension can be used thanks to custom extension <a href=\"https://bref.sh/docs/environment/php.html\" target=\"_blank\">Bref PHP</a></li>\n</ul>\n<p>But still I think this is a great starting point and I believe it can solve two major problems of the \"serverless PHP\":</p>\n<ul>\n<li>easily deploy process on serverless platforms </li>\n<li>make development with PHP frameworks like before</li>\n</ul>\n<h2>Further info</h2>\n<ul>\n<li><a href=\"https://bref.sh\" target=\"_blank\">Bref project</a></li>\n<li><a href=\"https://aws.amazon.com/blogs/apn/aws-lambda-custom-runtime-for-php-a-practical-example\" target=\"_blank\">PHP AWS Lambda</a> </li>\n</ul>","fields":{"slug":"/php-serverless-with-bref/","tags":["Symfony","PHP","serverless"]}}},{"node":{"id":"4847d312-706f-5678-9e9e-1a333f42095e","frontmatter":{"category":"Coding","title":"How we use ES6 generators to simplify our React Redux application code","date":"2019-04-04","summary":"How we use ES6 generators instead of thunk to simplify our React Redux application code and improve productivity","thumbnail":{"relativePath":"pages/es6-generators-react-redux/thumbnail.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAnLAAAJywEjDYgKAAADmUlEQVQ4y3VV2W/MURQemUY7+7Szd2Y681umLSHWB4TW1nqo5YUisYVIVGsJEXtrryUIam9Va0nQ1hoULYrEFhL8ASS2+A94+Zxzfp0xpR5ucnPPud893znfOdekqioUWqqiyFI0DVooAN2bDTUagaLrYpdFez5jm5YbFF+5k8SgZUoHVFQCi4QRmlIOb8V65A0fAd2Xk7rA++iIMfAsq0Zu2XRo4dweoClAOaDXtYAPgTlLkNn6Cq5tx5HV+hLu6sMUVRRqLM84a3kB95Y6ZLa9RnDGAmhBP4HqBsP0CIUq0bCdvInQtNnIt5gRGzgIjgMXYD/SAvvRNjj3NSPefwAKMvsgMHuxnHMQDJiKUPmLsvVMOyKjxxtUiL4WCsL89BsyHn+WaNS8qPiHJ5bJ42o89ifHEmEyqXpCAOxHWxEZW4qEwyIAjsOXkb1uL7I37Ifj4EWJKGHPQrhkChyHLlEeQ1AS+amgTCm65Kj7veJkO3UL2RsPwNr0AKYPv2Bt7oDlXKexb7wn4Lb623DsPw/d4+7Oo9YdYTwu1fItXi0AfW++Q+a1t/Cs2i5Uo6PHIV7QD0pBISLFpTA/+w7Pyq3ix8t69j7886sk/xIh64oTb23qoAsliA0eRrm5IZF6K9ZRdWNw7m2Cc/cZ0SBLhqnbTtxAbNBQhCeUwXKxS+wsOZNv0SoyXpfQOeGsNeeeRmQ8/ER7j9Ay/YAsZ22DpMX85AtcO06SwHMMoZMfp8A/r5IAF66U1wSQohFAei2j86OxJ6kkAV27TgtgRtdn2teLXYLwM+Ad+OcuTaNMuYiOKibtDRY5sMa8S9bKBb7MEWmRXIMy+QvlIcNJEZNgucCUG6QWqaLwZcv5R1SQN9IF3sqNMHd9kUdEFrQiYyZQob7CW7VJ/Pre+iCF9C9Y/qcohiAN2bCI7ceukrjvwl1TJw+Y3v+EpblTpJPcuzcfEmkxC06BFvSlySZN2Fwle12rVDvhssnUsR+5IsLOWVNLthY5SzitiBRNlHY0JlLiL2EnW49esTa2i/ak9ciZRcsVZ6rcFQJANga0NtxNa9tk6/UYDiGiQsNh6izkZ5kRL+wH187TUiSWFlc/Xtgf+TQceNJwetK7pNfx5Z9TIeOLx1bWledw1dYbo4kk5dp5Ss7YxoULzFxk5E/vZXz1GLAUIcsjOrLI0Fo3JRmwVHXPihqEJpf/f8D+9wsg8H++ADqTgRDq/Qv4DWMLuHUxNoXrAAAAAElFTkSuQmCC","width":325,"height":325,"src":"/static/2bee11a830bacc5ae9006df56b20c33a/b3029/thumbnail.png","srcSet":"/static/2bee11a830bacc5ae9006df56b20c33a/b3029/thumbnail.png 1x,\n/static/2bee11a830bacc5ae9006df56b20c33a/8d141/thumbnail.png 1.5x,\n/static/2bee11a830bacc5ae9006df56b20c33a/ee72c/thumbnail.png 2x,\n/static/2bee11a830bacc5ae9006df56b20c33a/5dfa8/thumbnail.png 3x"}}},"authorName":"Chirag Swadia","authorDescription":"Chirag is a Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/es6-generators-react-redux/avatar.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAUABQDASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAAAAECAwT/xAAXAQEBAQEAAAAAAAAAAAAAAAAEAwAB/9oADAMBAAIQAxAAAAGIveV5aObk0FjsCs//xAAbEAADAAIDAAAAAAAAAAAAAAAAAQIRIRIiQf/aAAgBAQABBQKnxmHTMGhGz0l9f//EABoRAAICAwAAAAAAAAAAAAAAAAABAhAxMkH/2gAIAQMBAT8B7U9mLB//xAAZEQABBQAAAAAAAAAAAAAAAAAAAQIQMTL/2gAIAQIBAT8BhuRbP//EABsQAAIBBQAAAAAAAAAAAAAAAAARAgEQIDFB/9oACAEBAAY/AmKcEatzCh//xAAbEAEAAwADAQAAAAAAAAAAAAABABEhMVFh8P/aAAgBAQABPyEnrfkRsPknmGxTsy8Dqp82W0JRuRFFn//aAAwDAQACAAMAAAAQ+Dj/AP/EABgRAAMBAQAAAAAAAAAAAAAAAAABETEQ/9oACAEDAQE/EG5ovBkf/8QAGBEAAgMAAAAAAAAAAAAAAAAAADEQESH/2gAIAQIBAT8Q2lCBh//EABwQAQADAQEAAwAAAAAAAAAAAAEAESExUXGB8P/aAAgBAQABPxCyt4AerkU0XY8TkPRXxBSQfql1NpWO/co8qKgOPZRgcYmBU9n/2Q==","width":50,"height":50,"src":"/static/8cf5c37636309895b29dd7ce5f1fcf28/d2d31/avatar.jpg","srcSet":"/static/8cf5c37636309895b29dd7ce5f1fcf28/d2d31/avatar.jpg 1x,\n/static/8cf5c37636309895b29dd7ce5f1fcf28/0b804/avatar.jpg 1.5x,\n/static/8cf5c37636309895b29dd7ce5f1fcf28/753c3/avatar.jpg 2x,\n/static/8cf5c37636309895b29dd7ce5f1fcf28/31ca8/avatar.jpg 3x"}}},"headerImage":{"relativePath":"pages/es6-generators-react-redux/headerImage.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsSAAALEgHS3X78AAABWUlEQVQY022QS0/CQBSFOzMtFLCdtsOrPOQRIPJogIILgkY0GqKJG5cu3GqMxIULExOJG/9s/0N7nBbjRiaZnJs7ky/nHEWRx63WRDqVCjRdR344DUV/jPxohlQmC0YpNE2Dqqp/SqkC+8BFuzBHTucRYzSK3xzHOY95SrXXF1KCbK2Fzv1T6L1+ofewQa7egtz/u0Sh6BZO0HBmOLT9SO4iohAYhrED6ooidJMHldUNvJdt6G22Uj/hXtyiO/TgTyeY+j4WiwUKpTxEtomheyVhE4wq64jr5RgKi/86LJZdQQkJ7MEUg8f3cPz2jeHzB+zRHLIKcM5hmqZUE2ktg4bto1NYomZ56BVPo6Yzjwgh8Z8d0G22BZGRWTaH8vIyrK/vUDm7hpoz9kauWqMk8lFphZY4jspGL3HIubUD5oUQjKlB0o+qhokythf21yOhiVLCkg7jOXb4A0fehWKiiDXIAAAAAElFTkSuQmCC","width":757,"height":236,"src":"/static/c49511e796013b6394df522c11a4a9fc/7eaf7/headerImage.png","srcSet":"/static/c49511e796013b6394df522c11a4a9fc/7eaf7/headerImage.png 1x"}}}},"html":"<h2>Background</h2>\n<p>When I first started working on React/Redux, the very first choice of library I used for handling asynchronous actions was <a href=\"https://github.com/reduxjs/redux-thunk\">Redux Thunk</a> as its maintained by the authors of Redux, and is very popular as well. Consider the following example, where an action type is being created for incrementing a counter and a corresponding action creator for it.</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token constant\">INCREMENT_COUNTER</span> <span class=\"token operator\">=</span> <span class=\"token string\">'INCREMENT_COUNTER'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">increment</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  type<span class=\"token operator\">:</span> <span class=\"token constant\">INCREMENT_COUNTER</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>Using redux thunk, an async action creator can be created as follows</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">incrementAsync</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token parameter\">dispatch</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setTimeout</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Pretty simple till now.</p>\n<h2>The Problem</h2>\n<p>Redux Thunk is easy to understand, but the problem arises when the application scales, and as the need for dispatching condition-based actions grows with the application, it leads to unmaintainable code. For example, consider the below code</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">makeSandwichesForEverybody</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">dispatch<span class=\"token punctuation\">,</span> getState</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>sandwiches<span class=\"token punctuation\">.</span>isShopOpen<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">resolve</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span>\n    <span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'My Grandma'</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n    Promise<span class=\"token punctuation\">.</span><span class=\"token function\">all</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span>\n      <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Me'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n      <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'My wife'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n    <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Our kids'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">then</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n    <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>myMoney <span class=\"token operator\">></span> <span class=\"token number\">42</span> <span class=\"token operator\">?</span>\n      <span class=\"token function\">withdrawMoney</span><span class=\"token punctuation\">(</span><span class=\"token number\">42</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">:</span>\n      <span class=\"token function\">apologize</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Me'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'The Sandwich Shop'</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>In the above code, there are too many callbacks and the code does not look clean. Also, it would become complex if more conditions are added to it later on. Then, how to simplify this?</p>\n<h2>ES6 Generators to the rescue</h2>\n<p>For our customer-facing websites like <a href=\"https://wirkaufendeinauto.de/auto-kaufen/\">wirkaufendeinauto</a> and <a href=\"https://www.autohero.com/de/\">AutoHero</a>, we are neither using Redux Thunk nor Redux Saga. Rather, we are using a very simple and lightweight npm module <a href=\"https://www.npmjs.com/package/redux-action-generators\">Redux Actions Generators</a> developed by our very own <a href=\"https://github.com/Tuch\">Alexander Afonin</a>, who works as a Senior Software Engineer at Auto1.\nIf this module is configured as a middleware in the React application, the above code can be simplified as shown below</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">makeSandwichesForEverybody</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">function</span><span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> getState <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>sandwiches<span class=\"token punctuation\">.</span>isShopOpen<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">yield</span> <span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'My Grandma'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">yield</span> <span class=\"token punctuation\">[</span><span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Me'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'My wife'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">yield</span> <span class=\"token function\">makeASandwichWithSecretSauce</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Our kids'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>myMoney <span class=\"token operator\">></span> <span class=\"token number\">42</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">yield</span> <span class=\"token function\">withdrawMoney</span><span class=\"token punctuation\">(</span><span class=\"token number\">42</span><span class=\"token punctuation\">)</span><span class=\"token operator\">:</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">yield</span> <span class=\"token function\">apologize</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Me'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'The Sandwich Shop'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Now you are ready to tackle the growing complexity with ease. Also, the code is clean and readable.</p>\n<p>One question that might arise is that why not use async/await with thunk actions which could have solved the problem that is being discussed earlier. But, there are advantages of using generators instead of async/await thunks which are listed below - </p>\n<h3>Testability</h3>\n<p>Redux Thunk returns promises, which are more difficult to test. Testing thunks often require complex mocking of the fetch API, Axios requests, or other functions. With generators, you do not need to mock functions wrapped with effects. This makes tests clean, readable and easier to write.</p>\n<h3>Error Handling</h3>\n<p>The best part about the Redux Actions Generator module is that you can catch all errors at one place, without the need to write multiple try catch blocks in different actions ( you can if you want to, but not mandatory ) With redux-thunk, this is not possible and you have to write error handlers everywhere, which makes the code look less readable.\nTo use this common error catching functionality, you can configure it while creating the store as shown below -</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">catchError</span> <span class=\"token operator\">=</span> <span class=\"token parameter\">error</span> <span class=\"token operator\">=></span> console<span class=\"token punctuation\">.</span><span class=\"token function\">error</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> \n<span class=\"token keyword\">const</span> middlewares <span class=\"token operator\">=</span> <span class=\"token function\">applyMiddleware</span><span class=\"token punctuation\">(</span><span class=\"token function\">createGeneratorMiddleware</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> catchError<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Once you do this, your actions can become clean and more readable. For example, the below code...</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">someAction</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">function</span><span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> api <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">yield</span> api<span class=\"token punctuation\">.</span><span class=\"token function\">loadSomeItems</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// handle error logic</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>can be replaced with...</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">someAction</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">function</span><span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> api <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">yield</span> api<span class=\"token punctuation\">.</span><span class=\"token function\">loadSomeItems</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>In this way, all the uncaught errors will be caught with the <code class=\"language-text\">catchError</code> function.</p>\n<h2>Enough of Making Sandwiches</h2>\n<p>Let's get to some real life example on how we use this pattern in our code. Consider the <a href=\"https://wirkaufendeinauto.de/auto-kaufen/\">Auto Kaufen page</a> on our wirkaufendeinauto website where we show a list of ads, filters, header, footer and some other content.</p>\n<p>For this module, we have some actions like</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">loadAds</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">filters</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n  <span class=\"token keyword\">function</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// filter is an object with some information like {make: 'Audi', model: 'A3'}</span>\n    \n    <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> ads<span class=\"token operator\">:</span> result <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">yield</span> api<span class=\"token punctuation\">.</span><span class=\"token function\">findAds</span><span class=\"token punctuation\">(</span>filters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// Once we get the ads list, we just save it in the redux store</span>\n  <span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">loadSimilarAds</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">filters</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n  <span class=\"token keyword\">function</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n      <span class=\"token comment\">//  this is same as loadAds, but the API endpoint from which it fetches data is different</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Similarly, we have other actions like <code class=\"language-text\">loadDataFromCms</code>, <code class=\"language-text\">trackGtmEvents</code> etc. Now the action which will be called when the main component mounts, will be as shown below</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">export</span> <span class=\"token keyword\">const</span> <span class=\"token function-variable function\">loadPage</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> \n  <span class=\"token keyword\">function</span><span class=\"token operator\">*</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> getState <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">yield</span> <span class=\"token function\">loadDataFromCms</span><span class=\"token punctuation\">(</span><span class=\"token string\">'header'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token keyword\">const</span> filters <span class=\"token operator\">=</span> <span class=\"token keyword\">yield</span> <span class=\"token function\">getFiltersFromStore</span><span class=\"token punctuation\">(</span><span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">yield</span> <span class=\"token punctuation\">[</span>\n        <span class=\"token function\">loadAds</span><span class=\"token punctuation\">(</span>filters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">loadMakeModelSubtype</span><span class=\"token punctuation\">(</span>filters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n        <span class=\"token function\">loadDataFromCms</span><span class=\"token punctuation\">(</span><span class=\"token string\">'home'</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n      <span class=\"token comment\">// If no ads found, we try to find similar ads which might interest the user</span>\n      <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span> <span class=\"token function\">getState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>ads<span class=\"token punctuation\">.</span>length <span class=\"token operator\">===</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          <span class=\"token keyword\">yield</span> <span class=\"token function\">loadSimilarAds</span><span class=\"token punctuation\">(</span>filters<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>As you can see, in the above code we are making multiple API calls, some are in parallel, and some are fired conditionally based on the results of the previous API calls. This way our redux actions look clean and are easy to debug and maintain.</p>\n<h2>Summary</h2>\n<p>So this is how you can make use of the ES6 generators to simplify your React application code. Comments and suggestions are welcome.</p>","fields":{"slug":"/es6-generators-react-redux/","tags":["auto1","engineering","react","redux"]}}},{"node":{"id":"cd170267-3e38-5f47-8461-d6f6583c5bed","frontmatter":{"category":"Coding","title":"Our love story with Deadlocks (PostgreSQL Edition)","date":"2019-03-15","summary":"How to get rid of deadlocks","thumbnail":{"relativePath":"pages/event-store-deadlock/thumbnail.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAYAAABG1c6oAAAACXBIWXMAAAsSAAALEgHS3X78AAAFFklEQVQ4y5WUeUzTZxjHi+AWnTuYc1mAKaiAIgoI4tR5henqgSBEoOOmCINxKAIiRPFCpK304CyUUikUtIisHC0UhHoy8ZoaY2Lcodv8w3+WxcyMtu937/ubOLNliXuSN2/yvu/zeb/P8b483t8WvjlkjTopTmCMiQzrXBm4uIyu8T94d0ZGdERYf3Ji/JWIUL4hThB1QZiW8dvuvD0kJzv7aSh/Qy89F8p71QKW+Krr1VrUdF3A4RYzxB0jqNYPQ9Oqg+a0AeJTFhxoNqNCN4zx+49x+f4TCKU9yKruQ233JVTVNcBz7hwlB5s21SFd096FhMo+69xY0YR3gsTmFlVuDS9tmzDd+IGs3aO2zYsVWb3ixXbPeIltUXKlLb+uh6h6x8iCBDFxF1RYhXKjtUVvwEezZpbxYmN2XKnoOI/Z0cdsyzOqEJxRRXyTT6DZOE6iDmqJd7yILM+sQlC6nCz7UkEC0+RwjylHUUM/aeq/ShanVOLjqDL7oVYLkhLifuRlZ2f/mlXdD+YYlK7gDmzIb4SyZwzugnJQZfClawwUsFPGzUvp+HD7YdR0X4ZQpCdUDMlXGiEUpjzh5eTkPs/kgBUkiCpYmCjBF0d1OHP+Dg5qzJxTaHEzfJMrqUoF/IRSrN1VD/mZixi99RBKwxiZtf2wvVw3gpgdEdd5aanC7/aqBuAZJ7KzkGhekCruxND1B8iQnsUIdWofvgX/VBnohVSxCKKOUbQN3YS08wIkp0bJbIHI2thtQbD/okZe2OaN3dLTFtCEW4MzFPBmQEknDp00w21HGVbn1EHVdxUbC1TwS5WyiznVm4vUEIr1pETVTz7JVdlqmlpAayzgec1xKVGeNiIwo9YamCb7SyEFitpHOThTxPK5rUQDll9vmtNd1QbsVw8g8fgpUqTss2dW9WFXTtZTCpzFOmedRF6DrQfaaUFOEAohu2t6UKwygcFZqE3945xCBmSFYd3QbLpGMqVdEOkvWRXtJvj7eKom+/qt3OysR4UqM1Nj90mSEJZDRddFzNxWiq371FAbx7GEFoNVlxWGqf5K3g3T1fvEdPMR8gqLnlOO+8uXsio4oLHhrAU+KTIrKwztQ9I+cgdFzaM43m5Bfl0vPATHQfc4aGC6nKoXEcvdx7bbt29j2htOJorZREfQJHN9pbwa0cfO2OZEHSHLMmuJXPs1KS0uxIOH3xPd8C0SkqdkKrnG9t8pY00O7fC3RNs9aC8+Ino2ZLmIrVu2WHkAHDji6pXmjqFrWLe37Q/d0A20tWhsRaVHJ3bX9k60nrtrL240sgpTUBVYrwqO6IiFttQh7Qj6xx+i6WQrPOfPa2KsKS9UekVGRv6k1XcjYnv47/UNKlju/QJJSw8GBs3IrTawgnFhe9Nw02UGyGWyZ1s+/+zKquVBndQ/5tUPZxLqSkciHd5sDvBdoJk5480TwpSkewUNA1zRgmmOPePFthK1GSlJiZfpOYdJCI2Wx/Px8fkn9F+2v6S4a59qEF4JYittGcJ+nQrdOURHhvW+AE1539nZ8aWDq6srN0+fPt3Bzc3N0cnJycHFxcWxp880la0X5OW0HmgepK9JbF1Bf5758ZKJ+i4LVgQuVrB9Pp/vyHsdCwsPd+LmTSF7taZvsCBFYaXtQ2LFPVBqdOyp8dm+h4fH6wGdnZ0n8zM7v6Dw55PGMSj0o7bGlg6sX/Np/YtwHXj/x9575+3J21P9Fi1E8FI/pkzxX+f/BBhq9luuZDT4AAAAAElFTkSuQmCC","width":315,"height":325,"src":"/static/fff962ac6bfdb5c2156f04c8855b288b/b3029/thumbnail.png","srcSet":"/static/fff962ac6bfdb5c2156f04c8855b288b/b3029/thumbnail.png 1x,\n/static/fff962ac6bfdb5c2156f04c8855b288b/8d141/thumbnail.png 1.5x"}}},"authorName":"Core Services Team","authorDescription":"Core Services team is responsible for infrastructure and platform development at AUTO1","authorAvatar":null,"headerImage":{"relativePath":"pages/event-store-deadlock/header.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAAAsSAAALEgHS3X78AAABoUlEQVQoz2MIjM+pDy/sfhxb3HkyNL/zXlbD9O+h2Y0XPD3c1RmAwM07gElKSooBhiUlxBlklDQYsAGDhIkMDP45Xf+t8hb9L5y66792/NT/wbUr/hTOOPDfN76whIEAMIjv5zRMmsJkmDiJH8QH0gwMftmdD21zZv8vmrT5l0v+7L/pXev/5XSv+hMUneLFzMCgr6ikrCApKckGdJ0QEAtKyynx8jEwcOiG1csZJk62B7rKDojVgIa5gm2JKWyf5V29+n9G19r/zkADg2pX/p+2bNtNDSVZM1ExcRNpaWkzoEFuQBwKxL5SUtJBEqLCrspmni7G6XMcDeInhAMNlDJMnJhpkDhRlCE6Jcc4pWrio/krNr4Pqlzw1zZz2r8J0+dddffwdAJZaGJqxg51HTcQqwANlBfhYmBTNvcWNEqdJQX0tiDQQFXDhEnyQFfKwoKDvTLJ28A9u/+jR/6M7xmemtIgwczMLCYGUkFxTSsjjB2bXbk3pahhE4i98/oXsLiysgoDcixLScswiAtwMQBdyGCUOpMR6EJQZDACXQnGAOs+imBvfQhTAAAAAElFTkSuQmCC","width":500,"height":168,"src":"/static/2d78359581a2f1861a243566e527e27a/7d852/header.png","srcSet":"/static/2d78359581a2f1861a243566e527e27a/7d852/header.png 1x"}}}},"html":"<h2>TL;DR</h2>\n<p>Always try to keep your transactions short and write your queries to deal with records in a deterministic order with respect to other transactions.</p>\n<h2>Full Story</h2>\n<p>Almost every non-trivial system needs some kind of task (job, event, whatever you call it) scheduling functionality at some point. Having more than 250 micro-services, ours was no exception.\nAt some point, it made sense to us to provide such functionality as a service for our developers. With <code class=\"language-text\">event-store</code> service, one simply can schedule a job to be executed at a specific time in future. There are already several ready to use tools for this specific purpose (e.g. BigBen, Quartz), however, because of several reasons (which are beyond the scope of this post) we decided to implement our own from scratch.</p>\n<p>Considering the subject of the post which is <code class=\"language-text\">Deadlocks</code>, we need a brief introduction on <code class=\"language-text\">event-store</code>'s implementation.</p>\n<p>An event on the server side is simply a record in the database. A simplified view of <code class=\"language-text\">events</code> table is as follow:</p>\n<table>\n<thead>\n<tr>\n<th>id</th>\n<th>event_type</th>\n<th>due_time</th>\n<th>start_process_time</th>\n<th>end_process_time</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>'5c55ea79-4774-49ae-96e2-975af7a41ce6'</td>\n<td>'user-cache-flush'</td>\n<td>'2019-01-01 00:00:00'</td>\n<td>null</td>\n<td>null</td>\n</tr>\n</tbody>\n</table>\n<p>The following is a bird's-eye view of what happens on the service:</p>\n<p><strong>Thread #1</strong><br>\na. The service periodically fetches a bunch of unprocessed events (those that are due and have no process time, neither start nor end) from the database (and marks them as <em>progressing</em> by filling the <code class=\"language-text\">start_process_time</code> column with the current timestamp). Let's call this <em>fetch-unprocessed</em> query.</p>\n<p>b. The service processes the events and marks them as <em>processed</em> (by filling the <code class=\"language-text\">end_process_time</code> column with the current timestamp). Let's call this <em>save-processed</em> query.</p>\n<p><strong>Thread #2</strong><br>\na. The service periodically checks the table and looks for stale events (those that are due and have <code class=\"language-text\">start_process_time</code> but no <code class=\"language-text\">end_process_time</code>). Let's call this <em>fetch-stale</em> query.</p>\n<p>b. The service marks them back as <em>unprocessed</em> (by setting <code class=\"language-text\">start_process_time</code> to <code class=\"language-text\">null</code>). Let's call this <em>release-stale</em> query.</p>\n<p>The very first MVP was a simple read-modify-write (anti-)pattern (with the help of Spring, JPA, and Hibernate). It is not hard to guess to what issue this implementation is vulnerable: Deadlocks.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">ERROR: deadlock detected\nDetail: Process 5234 waits for ShareLock on transaction 3465; blocked by process 467845.\n        Process 467845 waits for ShareLock on transaction 96575; blocked by process 5234.\nHint: See server log for query details.\nWhere: while updating tuple (14954,4) in relation \"events\"</code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">ERROR: deadlock detected\nDetail: Process 10438 waits for ExclusiveLock on tuple (14954,4) of relation 19118 of database 19113; blocked by process 31501.\n        Process 31501 waits for ShareLock on transaction 763124271; blocked by process 28450.\n        Process 28450 waits for ShareLock on transaction 763124277; blocked by process 28873.\n        Process 28873 waits for ExclusiveLock on tuple (14954,4) of relation 19118 of database 19113; blocked by process 10438.\nHint: See server log for query details.\nWhere: while locking tuple (6984,19) in relation \"events\"</code></pre></div>\n<p>In the beginning it was not a big deal, because deadlock errors were not frequent and we could live with it. However, very soon, after getting more clients, the deadlock issue (among other problems, e.g. lost-updates) started hurting the quality of the service (e.g. firing events twice).</p>\n<p>For the first attempt, we refactored the code to get rid of read-modify-write antipattern:</p>\n<div class=\"gatsby-highlight\" data-language=\"sql\"><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token comment\">-- fetch-unprocessed query</span>\n<span class=\"token keyword\">UPDATE</span> events event_to_update\n<span class=\"token keyword\">SET</span> start_process_time <span class=\"token operator\">=</span> <span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">FROM</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token keyword\">SELECT</span> id\n    <span class=\"token keyword\">FROM</span> events      \n    <span class=\"token keyword\">WHERE</span> end_process_time <span class=\"token operator\">is</span> <span class=\"token boolean\">NULL</span>\n            <span class=\"token operator\">AND</span> start_process_time <span class=\"token operator\">IS</span> <span class=\"token boolean\">NULL</span>\n            <span class=\"token operator\">AND</span> <span class=\"token punctuation\">(</span>due_time <span class=\"token operator\">BETWEEN</span> ? <span class=\"token operator\">AND</span> ?<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span> matched_event_for_update\n<span class=\"token keyword\">WHERE</span> event_to_update<span class=\"token punctuation\">.</span>id <span class=\"token operator\">=</span> matched_event_for_update<span class=\"token punctuation\">.</span>id\n<span class=\"token keyword\">RETURNING</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">-- release-stale query (including fetch-stale query)</span>\n<span class=\"token keyword\">UPDATE</span> events event_to_release\n<span class=\"token keyword\">SET</span> start_process_time <span class=\"token operator\">=</span> <span class=\"token boolean\">NULL</span>\n<span class=\"token keyword\">FROM</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token keyword\">SELECT</span> id\n    <span class=\"token keyword\">FROM</span> events\n    <span class=\"token keyword\">WHERE</span> end_process_time <span class=\"token operator\">IS</span> <span class=\"token boolean\">NULL</span> <span class=\"token operator\">AND</span> start_process_time <span class=\"token operator\">&lt;</span> ?\n<span class=\"token punctuation\">)</span> stuck_event\n<span class=\"token keyword\">WHERE</span> event_to_release<span class=\"token punctuation\">.</span>id <span class=\"token operator\">=</span> stuck_event<span class=\"token punctuation\">.</span>id\n<span class=\"token keyword\">RETURNING</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Obviously this is an improvement, though reduced the number of deadlocks, it didn't solve the issue completely.\nThe quickest solution to eliminate deadlocks was to change the isolation level to <code class=\"language-text\">Serializable</code>. However this is the last solution we wanted since it would hurt the performance and the quality of the service (think what would happen if one service start a transaction, fetch the events to process, but for some reason become stale).</p>\n<p>The better way to deal with deadlock is to analyze transactions and queries to prevent transaction interference by:</p>\n<ol>\n<li>making transactions short in terms of time</li>\n<li>writing queries to deal with records in a deterministic order</li>\n</ol>\n<p>By the first refactoring, we made transactions a bit shorter. But there's still some room for improvement. To apply the second best practice from the above we refactored the queries as follow (essentially ordering and acquiring a lock):</p>\n<div class=\"gatsby-highlight\" data-language=\"sql\"><pre class=\"language-sql\"><code class=\"language-sql\"><span class=\"token comment\">-- fetch-unprocessed query</span>\n<span class=\"token keyword\">UPDATE</span> events event_to_update\n<span class=\"token keyword\">SET</span> start_process_time <span class=\"token operator\">=</span> <span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">FROM</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token keyword\">SELECT</span> id\n    <span class=\"token keyword\">FROM</span> events      \n    <span class=\"token keyword\">WHERE</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token comment\">-- as before</span>\n    <span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> ID\n    <span class=\"token keyword\">FOR</span> <span class=\"token keyword\">NO</span> <span class=\"token keyword\">KEY</span> <span class=\"token keyword\">UPDATE</span>\n<span class=\"token punctuation\">)</span> matched_event_for_update\n<span class=\"token keyword\">WHERE</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token comment\">-- as before</span>\n<span class=\"token keyword\">RETURNING</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">-- release-stale query (including fetch-stale query)</span>\n<span class=\"token keyword\">UPDATE</span> events event_to_release\n<span class=\"token keyword\">SET</span> start_process_time <span class=\"token operator\">=</span> <span class=\"token boolean\">NULL</span>\n<span class=\"token keyword\">FROM</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token keyword\">SELECT</span> id\n    <span class=\"token keyword\">FROM</span> events\n    <span class=\"token keyword\">WHERE</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token comment\">-- as before</span>\n    <span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> ID\n    <span class=\"token keyword\">FOR</span> <span class=\"token keyword\">NO</span> <span class=\"token keyword\">KEY</span> <span class=\"token keyword\">UPDATE</span>\n<span class=\"token punctuation\">)</span> stuck_event\n<span class=\"token keyword\">WHERE</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token comment\">-- as before</span>\n<span class=\"token keyword\">RETURNING</span> <span class=\"token operator\">*</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>However, the deadlocks were still appearing intermittently:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">ERROR: deadlock detected\nDetail: Process 7534 waits for ShareLock on transaction 93897000; blocked by process 13376.\n        Process 13376 waits for ShareLock on transaction 93896994; blocked by process 7534.\nHint: See server log for query details.\nWhere: while rechecking updated tuple (134131,3) in relation \"events\"</code></pre></div>\n<p>Of course! we still had one transaction/query dealing with records in a non deterministic way: <code class=\"language-text\">JpaRepository.save(Iterable&lt;S> entities)</code>. In the code, after fetching events to be processed, we flag (<code class=\"language-text\">UPDATE</code>) the process events as <code class=\"language-text\">processed</code>, and also save (<code class=\"language-text\">INSERT</code>) new events spawned by the processed events. Here's the catch: the event processing is done in <em>parallel</em>. So the resulting list of events (both processed and newly created ones) is not ordered with respect to other transactions. So the third refactoring was to restore the order of processed events:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token comment\">/**\n * To process events.\n * The result list will be ordered with respect to the given list.\n * All new events will be added at the end of the result list.\n * @param events events to be processed\n * @return list of processed and created events\n */</span>\n<span class=\"token keyword\">private</span> <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Event</span><span class=\"token punctuation\">></span></span> <span class=\"token function\">doProcessEvents</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Event</span><span class=\"token punctuation\">></span></span> events<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token class-name\">ProcessingResult</span> result <span class=\"token operator\">=</span> eventProcessor<span class=\"token punctuation\">.</span><span class=\"token function\">processInParallel</span><span class=\"token punctuation\">(</span>events<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Event</span><span class=\"token punctuation\">></span></span> successfulEvents <span class=\"token operator\">=</span> result<span class=\"token punctuation\">.</span><span class=\"token function\">getSucceeded</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// may contain new events;</span>\n    <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Event</span><span class=\"token punctuation\">></span></span> failedEvents <span class=\"token operator\">=</span> result<span class=\"token punctuation\">.</span><span class=\"token function\">getFailed</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token class-name\">List</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Event</span><span class=\"token punctuation\">></span></span> allEvents <span class=\"token operator\">=</span> <span class=\"token class-name\">ListUtils</span><span class=\"token punctuation\">.</span><span class=\"token function\">union</span><span class=\"token punctuation\">(</span>successfulEvents<span class=\"token punctuation\">,</span> failedEvents<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token class-name\">Map</span><span class=\"token generics\"><span class=\"token punctuation\">&lt;</span>UUID<span class=\"token punctuation\">,</span> <span class=\"token class-name\">Integer</span><span class=\"token punctuation\">></span></span> eventIndices <span class=\"token operator\">=</span> <span class=\"token function\">range</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> events<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">boxed</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">.</span><span class=\"token function\">collect</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">CollectorUtils</span><span class=\"token punctuation\">.</span><span class=\"token function\">toMap</span><span class=\"token punctuation\">(</span>i <span class=\"token operator\">-></span> events<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getId</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> i <span class=\"token operator\">-></span> i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token comment\">// This should sort according to the original order and put all new events at the end.</span>\n    allEvents<span class=\"token punctuation\">.</span><span class=\"token function\">sort</span><span class=\"token punctuation\">(</span><span class=\"token function\">comparingInt</span><span class=\"token punctuation\">(</span>event <span class=\"token operator\">-></span> eventIndices<span class=\"token punctuation\">.</span><span class=\"token function\">getOrDefault</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">.</span><span class=\"token function\">getId</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token class-name\">Integer</span><span class=\"token punctuation\">.</span>MAX_VALUE<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">return</span> allEvents<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>After this last change, we saw the game for deadlocks was over: <em>\"Goodbye Deadlock!\"</em></p>","fields":{"slug":"/event-store-deadlock/","tags":["deadlock","sql","transaction","postgresql"]}}},{"node":{"id":"7efdac28-b97f-53e0-adf8-48d022f3eecc","frontmatter":{"category":"Coding","title":"Integration Test Speedup with Spring","date":"2019-03-11","summary":"Here is what we found on speeding up your integration tests in spring based applications.","thumbnail":null,"authorName":"Boris Faniuk","authorDescription":"Boris is a former member of Engineering of AUTO1 Group.","authorAvatar":{"relativePath":"pages/integration-test-speedup/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/integration-test-speedup/header.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAPABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAABQABAv/EABYBAQEBAAAAAAAAAAAAAAAAAAIAAf/aAAwDAQACEAMQAAABJ6Uw4FJSv//EABsQAAICAwEAAAAAAAAAAAAAAAECAAMEFCEx/9oACAEBAAEFAl9tuawzH6WUPNYT/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQIBAT8BJ//EABsQAAEEAwAAAAAAAAAAAAAAAAABEBIhIjFR/9oACAEBAAY/AjJo9SizZ//EABwQAQEAAgIDAAAAAAAAAAAAAAERAHEQMUFR0f/aAAgBAQABPyFMdusqfAgeuBQwbbGHwF1jT4z/2gAMAwEAAgADAAAAELsf/8QAFhEBAQEAAAAAAAAAAAAAAAAAARBB/9oACAEDAQE/EA2f/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERIf/aAAgBAgEBPxDSpD//xAAbEAEBAQADAQEAAAAAAAAAAAABEQAhMXFBYf/aAAgBAQABPxAMiBZ241OQL4wZbyughIofpPEuZhdFS61EeZ//2Q==","width":1024,"height":768,"src":"/static/9f60dcc74069c89c91db86dc33946167/9f594/header.jpg","srcSet":"/static/9f60dcc74069c89c91db86dc33946167/9f594/header.jpg 1x"}}}},"html":"<h2>Problem statement</h2>\n<p>Over time we realized that our microservices built on top of Spring framework take tons of time on the integration test step. Every single PR runs all tests and this takes 10-20 minutes for some services. To decrease PR build time we decided to research why this happens.\nOne of the problems that this research highlighted is ramping up heavy spring context several times during execution of all module’s tests.</p>\n<p>As a proof of concept we have taken 3 modules and cleaned up their tests to achieve better integration test performance.</p>\n<p>The results are pretty much self-explanatory: </p>\n<ol>\n<li>Module A now takes 3 minutes to test versus 11 before</li>\n<li>Module B now takes 3 minutes to test versus 8 before</li>\n<li>Module C now takes 4 minutes to test versus 12 before</li>\n</ol>\n<p>Below I list all factors that produce many spring contexts and how we managed to overcome them.</p>\n<h2>Spring features to be avoided</h2>\n<h3><code class=\"language-text\">@ActiveProfiles</code> and <code class=\"language-text\">@ContextConfiguration</code> with different attributes</h3>\n<p>Our spring-based microservices actively use spring profiles and configuration classes.\nMany components from common libraries are hidden under profiles and configuration classes to not be active for every single module / environment without need. So, integration test authors define profiles and configuration classes that should be activated for their tests using these annotations:</p>\n<ol>\n<li><code class=\"language-text\">@ActiveProfiles({\"integration-test\", \"pg-test\", \"mongo-test-two-nodes\"})</code></li>\n<li><code class=\"language-text\">@ContextConfiguration(classes = {Application.class, AwsTestConfiguration.class})</code></li>\n</ol>\n<p>Here <em>mongo-test-two-nodes</em> activates special mode for mongo based services to operate with two separate mongo instances. As not all tests need this, the profile is turned off by default and only those tests that need this behaviour would explicitly turn it on. But this, unfortunately, leads to multiple spring contexts being created.</p>\n<p>The same happens with <em>AwsTestConfiguration</em> that deploys special test-component to mock AWS calls.</p>\n<p>The solution was to make all tests use the same set of active profiles and context configuration classes for every single integration test.\nThe drawback is that some components are deployed, even for the tests that do not need it. But deploying single component takes O(1) time comparing with the whole spring context.</p>\n<p>Another point to keep in mind is that order of profiles (configuration classes) matters.\n<code class=\"language-text\">@ActiveProfiles({\"integration-test\", \"pg-test\"})</code>\n<code class=\"language-text\">@ActiveProfiles({\"pg-test\", \"integration-test\"})</code></p>\n<p>Two settings mentioned above result in 2 different spring contexts.</p>\n<h3><code class=\"language-text\">@SpyBean</code> and <code class=\"language-text\">@MockBean</code></h3>\n<p>One interesting feature in spring-boot-test is mocking / spying real spring beans.\nThis was mostly used when we don’t care what some method does in test but we need to check that it was called by parent components.\nUnfortunately this also makes test to create separate spring context.\nWhat we’ve done here is replacing <code class=\"language-text\">@SpyBean</code> annotation with configuration class that wraps real spring bean into <code class=\"language-text\">Mockito.spy(..)</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">@Configuration\npublic class SomeComponentSpyFactory {\n\t@Autowired\n\tprivate SomeComponent someComponent;\n\n\t@Bean\n\t@Primary\n\tpublic SomeComponent someComponentSpy() {\n    \t\treturn Mockito.spy(someComponent);\n\t}\n}</code></pre></div>\n<p>Another option is to use the combination of <code class=\"language-text\">@Autowired</code> and <code class=\"language-text\">@Spy</code> annotations.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">\t@InjectMocks\n\t@Autowired\n\tprivate ParentComponent parentComponent;\n\n\t@Spy\n\t@Autowired\n\tprivate ChildComponent childComponent;</code></pre></div>\n<p>However, the drawback of the last solution is that, <em>parentComponent</em> needs to have a setter for <em>childComponent</em> which is not good in terms of encapsulation. But if you don’t use autowiring on constructor level it is fine. Anyway, one can choose whatever fits the situation better.</p>\n<h3><code class=\"language-text\">@DirtiesContext</code></h3>\n<p>One of the services used this annotation to clear the caches between different tests.\nClearing a cache is really a problem (see section below), but this solution comes to separate spring context per test class or even test method (depending on annotation parameters). Context per method was actually the case for a few test classes. Instead in this modules we added methods to clear the caches programmatically without deploying the whole new context.\nOne can use java reflection API instead of adding special production-level methods, again whatever fits you better.</p>\n<h2>Challenge: test execution order and cleaning collections (caches)</h2>\n<p>After all this “multiple context” factors are gone one may face (and we did) a challenge to fix or re-organize some tests. Before above enhancements were done all tests were running in separate spring contexts, therefore used separate instances of every component and therefore those problems could be hidden.</p>\n<p>As an example some tests in mongo-based service were testing <code class=\"language-text\">getAll()</code>-like operations. Those tests were running functions that fetched all records from some collections. This was not a problem as embedded mongo DB was different instance. After all tests started to exploit the same spring context some of them started to fail intermittently. The failures were intermittent because test execution order is different. One service may break another, but not vice versa.\nSo, to overcome this, we added missing <code class=\"language-text\">@Before</code> operations that cleaned those collections.</p>\n<p>The rule that I would suggest here is that every test should clean up whatever it needs to be clean and not rely on fairness of other tests. That was a problem in our case. Some tests had <code class=\"language-text\">@After</code> operations that cleaned up, but not everything produced by the test was cleaned up. This caused intermittent failures of other tests.</p>\n<h2>Tools we created to reduce test execution time</h2>\n<p>So, now after we know all this, we created two tools (and may create more in future) that help to identify those problems.</p>\n<h3>Jenkins PR pipeline step</h3>\n<p>After every PR commit we run one additional step that analyzes test execution log.\nIf more than one spring context is created this leaves some traces and a notification is sent to the author of the commit via slack</p>\n<p>As an enhancement, the jenkins jobs could be modified to fail the build if the number of spring contexts is greater than a certain threshold. The threshold could start with a high number and can gradually be reduced as the team cleans up the existing tests by adopting the aforementioned practices/fixes</p>\n<h3>IntelliJ IDEA plugin</h3>\n<p>We wrote an IntelliJ plugin to identify and solve the aforementioned problems. There will be a separate blog post about this plugin coming very soon.</p>","fields":{"slug":"/integration-test-speedup/","tags":["auto1","engineering","spring","java","testing"]}}},{"node":{"id":"99158851-0237-5904-98ca-02b5e2f45684","frontmatter":{"category":"Coding","title":"Spring 5 candidate component index case study","date":"2019-02-05","summary":"Analysis of Spring 5.X candidate component index applicability to boost our application startup time","thumbnail":{"relativePath":"pages/spring-5-indexer/thumbnailImage.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAZABQDASIAAhEBAxEB/8QAFwABAQEBAAAAAAAAAAAAAAAAAAIBBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAeBWySoZgAf/xAAaEAACAgMAAAAAAAAAAAAAAAAAARASICEx/9oACAEBAAEFAisLg95//8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAFBABAAAAAAAAAAAAAAAAAAAAMP/aAAgBAQAGPwJP/8QAGhAAAwADAQAAAAAAAAAAAAAAAAERECAxIf/aAAgBAQABPyFK8Kx5obfaNVLt/9oADAMBAAIAAwAAABBTBzz/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAcEAEAAgMBAQEAAAAAAAAAAAABABEhMUFRYSD/2gAIAQEAAT8QR0FfCY14dprVxKUeSiVurchzX3sU1d7c6ZqWULr2CBDvz9f/2Q==","width":265,"height":325,"src":"/static/85788e7deb4eaccc84801ebd1f7b77a8/a2998/thumbnailImage.jpg","srcSet":"/static/85788e7deb4eaccc84801ebd1f7b77a8/a2998/thumbnailImage.jpg 1x,\n/static/85788e7deb4eaccc84801ebd1f7b77a8/99cce/thumbnailImage.jpg 1.5x"}}},"authorName":"Mariusz Sondecki","authorDescription":"Mariusz is Senior Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/spring-5-indexer/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/spring-5-indexer/headerImage.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAANABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAECBv/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAc/UgxB//8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQABBQJf/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPwE//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPwE//8QAFBABAAAAAAAAAAAAAAAAAAAAIP/aAAgBAQAGPwJf/8QAGBAAAwEBAAAAAAAAAAAAAAAAAAERIEH/2gAIAQEAAT8hElKxzmP/2gAMAwEAAgADAAAAEPPP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAGxAAAgIDAQAAAAAAAAAAAAAAAREAECExQVH/2gAIAQEAAT8Qm5fABBZ6Hh5TKTxX/9k=","width":1280,"height":853,"src":"/static/430c76d0d1e83aad3065e86e11366218/966a5/headerImage.jpg","srcSet":"/static/430c76d0d1e83aad3065e86e11366218/966a5/headerImage.jpg 1x,\n/static/430c76d0d1e83aad3065e86e11366218/aa36d/headerImage.jpg 1.5x"}}}},"html":"<h2>The situation</h2>\n<p>Since day one at AUTO1, we strongly believe that the microservice architecture helps us run business at scale not only due to the technical benefits it brings but also, if not foremost by allowing many teams to work independently from each other. Today, we’re running more than 250 microservices in production and on average add one more to our platform every week. All of them are powered by the Spring Framework technology stack, which we value very much for its productivity, but at the same time consider it to be a bit heavy in terms of bootstrapping time. The typical startup time of our Spring applications varies between 40 and 80 seconds. Since we do around 30 deployments per day, our engineering teams spend roughly 30 minutes daily waiting for the deployments to be completed. As we value the time of our engineering teams, we wanted to find a way to decrease these numbers. </p>\n<h2>A new hope</h2>\n<p>While investigating the startup times of our applications, we have identified classpath component scanning as a potential place to look for improvements. Luckily for us, some of our tech savvy engineers suggested a not so prominent Spring 5.X feature to come at help here - the build time component candidate index.\nThe build time component index is an alternative for regular component scanning, which skips the classpath search operation in favor of using a compile time pre-generated index of component candidates during the spring application context building. However, it comes with a small print from the Spring Framework experts saying that this functionality should have mostly a visible impact on startup times for applications with large amount of beans and that are operating in environments where IO operations are expensive (e.g. remote file systems) or where JVM security managers are in use. Although, neither of this is our use case, we have decided to proceed with the feature evaluation and measurements, as here at AUTO1, we like our decisions to be data driven.</p>\n<h2>Demystifying the indexer</h2>\n<p>The key part of the indexer feature is a pre-generated index file located in <em><span style=\"font-family:Courier New;\">META-INF/spring.components</span></em> one per JAR. Every index entry in this file is a fully qualified name of a candidate component as a key and comma separated stereotypes as value. So for example “X=Y, Z” can be read simply as register a candidate component X with following stereotypes Y, Z. Below is an example of a <em><span style=\"font-family:Courier New;\">spring.components</span></em> file:</p>\n<div class=\"gatsby-highlight\" data-language=\"shell\"><pre class=\"language-shell\"><code class=\"language-shell\">com.auto1.playground.service.SpringDummyService=org.springframework.stereotype.Component\ncom.auto1.playground.domain.SpringDummy=javax.persistence.Entity,javax.persistence.Table,javax.persistence.EntityListeners\ncom.auto1.playground.repository.SpringDummyRepository=org.springframework.stereotype.Component,org.springframework.data.repository.Repository\ncom.auto1.playground.configuration.LocalConfiguration=org.springframework.stereotype.Component\ncom.auto1.playground.service.IndexedCustomService=com.auto1.playground.service.IndexedCustomService\ncom.auto1.playground.Application=org.springframework.stereotype.Component\ncom.auto1.playground.SpringDummyController=org.springframework.stereotype.Component\ncom.auto1.playground.service.IndexedCustomExample=com.auto1.playground.annotation.IndexedCustom</code></pre></div>\n<p>The first question that arises here is how to create such a file and keep it up-to-date. The Spring engineers thought about this problem as well and came up with an annotation processor tool called <a href=\"https://github.com/spring-projects/spring-framework/tree/master/spring-context-indexer\">spring indexer</a> that hooks in during the project build phase and generates the file. Making use of it is fairly simple, assuming you are using your favorite build automation tool, in our case maven and want our IDE to keep this file up to date, simply add the spring indexer annotation processor to your pom file:</p>\n<div class=\"gatsby-highlight\" data-language=\"xml\"><pre class=\"language-xml\"><code class=\"language-xml\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>build</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>plugins</span><span class=\"token punctuation\">></span></span>\n        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>plugin</span><span class=\"token punctuation\">></span></span>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>groupId</span><span class=\"token punctuation\">></span></span>org.apache.maven.plugins<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>groupId</span><span class=\"token punctuation\">></span></span>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>artifactId</span><span class=\"token punctuation\">></span></span>maven-compiler-plugin<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>artifactId</span><span class=\"token punctuation\">></span></span>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>version</span><span class=\"token punctuation\">></span></span>3.5<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>version</span><span class=\"token punctuation\">></span></span>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>configuration</span><span class=\"token punctuation\">></span></span>\n                <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>annotationProcessorPaths</span><span class=\"token punctuation\">></span></span>\n                    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>path</span><span class=\"token punctuation\">></span></span>\n                        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>groupId</span><span class=\"token punctuation\">></span></span>org.springframework<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>groupId</span><span class=\"token punctuation\">></span></span>\n                        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>artifactId</span><span class=\"token punctuation\">></span></span>spring-context-indexer<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>artifactId</span><span class=\"token punctuation\">></span></span>\n                    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>path</span><span class=\"token punctuation\">></span></span>\n                <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>annotationProcessorPaths</span><span class=\"token punctuation\">></span></span>\n            <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>configuration</span><span class=\"token punctuation\">></span></span>\n        <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>plugin</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>plugins</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>build</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>Once this is done, what happens during project build time is the spring context indexer (precisely speaking the <a href=\"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/index/CandidateComponentsIndex.html\">CandidateComponentsIndexer</a> class) while going through the project identifies annotated components and outputs them to <em><span style=\"font-family:Courier New;\">META-INF/spring.components</span></em>. The type of components it includes in the candidate list are:</p>\n<ol>\n<li>\n<p>Classes annotated directly or indirectly with spring <em><span style=\"font-family:Courier New;\">@Component</span></em> annotation (which by itself is meta annotated with <em><span style=\"font-family:Courier New;\">@Indexed</span></em>) and other stereotypes for which <em><span style=\"font-family:Courier New;\">@Component</span></em> is a meta annotation such as <em><span style=\"font-family:Courier New;\">@Repository</span></em>, <em><span style=\"font-family:Courier New;\">@Controller</span></em>, <em><span style=\"font-family:Courier New;\">@Service</span></em>, <em><span style=\"font-family:Courier New;\">@Configuration</span></em>.</p>\n</li>\n<li>\n<p>Classes and interfaces annotated with annotations from <em><span style=\"font-family:Courier New;\">javax</span></em> package, including <em><span style=\"font-family:Courier New;\">CDI</span></em> annotations (<em><span style=\"font-family:Courier New;\">@Named<span></em>, <em><span style=\"font-family:Courier New;\">@ManagedBean</span></em>), <em><span style=\"font-family:Courier New;\">JPA</span></em> annotations (<em><span style=\"font-family:Courier New;\">@Entity</span></em>, <em><span style=\"font-family:Courier New;\">@EntityListeners</span></em>) or even <em><span style=\"font-family:Courier New;\">Servlet</span></em> annotations (<em><span style=\"font-family:Courier New;\">@WebListener</span></em>)</p>\n</li>\n<li>\n<p>Any custom classes and interfaces annotated with <em><span style=\"font-family:Courier New;\">@Indexed</span></em> annotation. </p>\n</li>\n</ol>\n<p>It should be noted that applying <em><span style=\"font-family:Courier New;\">@Indexed</span></em> on a class/interface where no other standard stereotype (as from points 1 and 2) is present will not make by itself the bean managed, thus not making them eligible for being autowired, but merely provide a hint that it represents a stereotype to be considered in the index. </p>\n<p>Example of the <em><span style=\"font-family:Courier New;\">@Indexed</span></em> annotation usage:</p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Indexed</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">IndexedCustomService</span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Or as meta annotated as below: </p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@Target</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">ElementType</span><span class=\"token punctuation\">.</span>TYPE<span class=\"token punctuation\">)</span>\n<span class=\"token annotation punctuation\">@Retention</span><span class=\"token punctuation\">(</span><span class=\"token class-name\">RetentionPolicy</span><span class=\"token punctuation\">.</span>RUNTIME<span class=\"token punctuation\">)</span>\n<span class=\"token annotation punctuation\">@Documented</span>\n<span class=\"token annotation punctuation\">@Indexed</span>\n<span class=\"token keyword\">public</span> <span class=\"token annotation punctuation\">@interface</span> <span class=\"token class-name\">IndexedCustom</span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span>\n\n<span class=\"token annotation punctuation\">@IndexedCustom</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">IndexedCustomExample</span> <span class=\"token punctuation\">{</span> <span class=\"token punctuation\">}</span></code></pre></div>\n<p>In order to make them available in the application context, thus autowirable, we could for example include them in the component scan filters as shown below: </p>\n<div class=\"gatsby-highlight\" data-language=\"java\"><pre class=\"language-java\"><code class=\"language-java\"><span class=\"token annotation punctuation\">@SpringBootApplication</span>\n<span class=\"token annotation punctuation\">@ComponentScan</span><span class=\"token punctuation\">(</span>basePackages<span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token string\">\"com.auto1\"</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> includeFilters <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token annotation punctuation\">@ComponentScan.Filter</span><span class=\"token punctuation\">(</span>type<span class=\"token operator\">=</span> ANNOTATION<span class=\"token punctuation\">,</span> value <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token class-name\">IndexedCustomExample</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token annotation punctuation\">@ComponentScan.Filter</span><span class=\"token punctuation\">(</span>type<span class=\"token operator\">=</span> ASSIGNABLE_TYPE<span class=\"token punctuation\">,</span> value <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span><span class=\"token class-name\">IndexedCustomService</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">class</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">public</span> <span class=\"token keyword\">class</span> <span class=\"token class-name\">Application</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">WebMvcConfigurer</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>There is one big pitfall that comes with the feature though, that is by default the index is automatically enabled when a <em><span style=\"font-family:Courier New;\">META-INF/spring.components</span></em> file is found on the classpath during application start-up and this in turn, disables completely the regular classpath component scanning. In other words, both the index and classpath scanning cannot be used at the same time. The consequence of this is that if an index is available for some JARs, but is incomplete due to including other JARs that come with potential bean candidates but don’t have the index file generated, those beans will not be discovered, thus application startup might spectacularly fail with a well known error: <em><span style=\"font-family:Courier New;\">“X required a bean of type 'Y’ that could not be found”</span></em>.\nFortunately, Spring engineers, as thoughtful as they are, provided a feature flag <em><span style=\"font-family:Courier New;\">spring.index.ignore</span></em> that can be passed either as a system property or set in the <em><span style=\"font-family:Courier New;\">spring.properties</span></em> file at the root of the classpath allowing us to disable the usage of the candidate component index altogether. </p>\n<h2>Test me one more time</h2>\n<p>Like mentioned before, the aim of our investigation was to understand if the Spring indexer feature is of any help to us in regards to boosting the application start-up times. In order to make the test fairly reliable and control as many confounding factors as possible, we have decided to run the test firstly, using a “dummy” Spring 5 application (in two flavors - with 120 and 5000 beans) using all the features a production microservice would use, on a bare metal machine i.e. a <span style=\"font-family:Courier New;\">MacBook Pro late 2017 i7</span>. Secondly, running a real life production service in a less controlled but close to production environment i.e. on a <span style=\"font-family:Courier New;\">r4.8xlarge</span> EC2 instance with other services running concurrently. The applications themselves were using <span style=\"font-family:Courier New;\">Spring 5.0.10.RELEASE</span> with <span style=\"font-family:Courier New;\">Spring Cloud Finchley.SR2</span> release train.\nAfter making a couple of hundred measurements of application bootstrapping times with candidate component index enabled / disabled and verifying in the logs that Spring was indeed using (or not) the component candidate list, we ended up with following averaged results:</p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/30322fc0fcb831c8c776c8ac7df43562/a0e60/measurements.jpg\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 590px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 70%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAOABQDASIAAhEBAxEB/8QAGAAAAgMAAAAAAAAAAAAAAAAAAAMCBAX/xAAVAQEBAAAAAAAAAAAAAAAAAAABAv/aAAwDAQACEAMQAAAB3qb1i4kM/wD/xAAaEAACAwEBAAAAAAAAAAAAAAABAgAREhMD/9oACAEBAAEFArnUxDaP56PGKMr/AP/EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABgQAQEAAwAAAAAAAAAAAAAAAAABEDFB/9oACAEBAAY/AnEuNpH/xAAYEAEBAQEBAAAAAAAAAAAAAAABEQAhMf/aAAgBAQABPyFB6husmO16mK1mi2t3Gw3/2gAMAwEAAgADAAAAEJM//8QAGhEAAgIDAAAAAAAAAAAAAAAAABEBIYHh8P/aAAgBAwEBPxCF2dENWf/EABoRAAICAwAAAAAAAAAAAAAAAAARASGB4fD/2gAIAQIBAT8Ql9jZKdH/xAAdEAEBAAEEAwAAAAAAAAAAAAABEQAhMUFhccHR/9oACAEBAAE/EF55xmDyDZWb6p6yXcazAScAaHdwDquO37giISrzn//Z'); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Measurements\"\n        title=\"\"\n        src=\"/static/30322fc0fcb831c8c776c8ac7df43562/f8fb9/measurements.jpg\"\n        srcset=\"/static/30322fc0fcb831c8c776c8ac7df43562/e8976/measurements.jpg 148w,\n/static/30322fc0fcb831c8c776c8ac7df43562/63df2/measurements.jpg 295w,\n/static/30322fc0fcb831c8c776c8ac7df43562/f8fb9/measurements.jpg 590w,\n/static/30322fc0fcb831c8c776c8ac7df43562/a0e60/measurements.jpg 800w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n      />\n  </span>\n  </a></p>\n<h2>The expected disappointment</h2>\n<p>As the above results have consistently shown, there was no improvement or even insignificant worsening (which will be a subject of our analysis in a separate article) of the bootstrapping time of the Spring applications, regardless of the number of candidate beans present, when using the pre-generated candidate component index. This was expected, as explained in the opening section, the conditions for which this feature was designed (slow or expensive IO operations) are simply not met in our case. One more important factor to consider here, is that a great deal of the beans in our Spring applications, is created using bean definition factory methods, which are not subject to the component classpath scanning, thus are not impacted by this feature. </p>\n<p>All in all, we deemed this feature not to be useful for our purposes and moved on to the next item on our list.</p>","fields":{"slug":"/spring-5-indexer/","tags":["spring","spring-indexer","bootstrapping","performance"]}}},{"node":{"id":"f7a13c08-6929-58c2-9d9e-eae3b357b1e1","frontmatter":{"category":"Coding","title":"Exploring technologies with Docker","date":"2018-12-19","summary":"Yet another use case for using containers.","thumbnail":{"relativePath":"pages/exploring-technologies-with-docker/thumbnailImage.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,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","width":265,"height":325,"src":"/static/753d78469abf65ded853c2e0d4fb7aec/b3029/thumbnailImage.png","srcSet":"/static/753d78469abf65ded853c2e0d4fb7aec/b3029/thumbnailImage.png 1x,\n/static/753d78469abf65ded853c2e0d4fb7aec/8d141/thumbnailImage.png 1.5x"}}},"authorName":"Marcin Sałata","authorDescription":"Marcin is Senior Software Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/exploring-technologies-with-docker/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/exploring-technologies-with-docker/headerImage.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABsUlEQVQY0zWR32/SUBiG+x8bM0IJMp2BjQ3SKgzTFlpWKG0puBloOefwQ5jbUDezC70wu9minO87JE6N/gPWYuLt+zwX7/t9kuacrpvtC9EgNjyhJeFRBX2mwg4rr+vkCDZs4/z3NtkOOxAdUgHTX6BpX6zr0RE8HZexTRQhxWQPf4Q6WCdDyHofYD42VqcT42vWu8RNdj80ICZFjOkufg81ME/Cf96CNlfxpMB/hi+weTyAR/41TEZNLrlsFytkHzPdN5Bu3IpMdwnp3lv+wPgittz3UKMl6LACBqSEhyMVMv4ZbJk3Qu4vwKEKV6PnmPLeYca6wYfdBUra9ADLkyLk+jOQzVvMutdQda94rXUlDNJa5V8X4ZBVMNWbY7r1CbdfTrkyqqBFNFCDBa+6c2FQe5VnNTAjA6WY5fFbMkXrjyHrfkSawD/jIv891NF5dQy57mUyTwdKrIR/BqPP4D6qQjzO8zhp+GvQwPbGC5YwpwaXnA4TPWcmbGLxXKhgMHoGEStwPdxH2TvHVP1OPA6m6EYqbkcK2smdgvZMuD7FAd0DPSwK2VtiunEn5ORJfwFIJFacA7WGDwAAAABJRU5ErkJggg==","width":1280,"height":392,"src":"/static/be0acc48b4db44e7e3d00e2d5c353dc3/26421/headerImage.png","srcSet":"/static/be0acc48b4db44e7e3d00e2d5c353dc3/26421/headerImage.png 1x,\n/static/be0acc48b4db44e7e3d00e2d5c353dc3/34a7a/headerImage.png 1.5x"}}}},"html":"<h2>tl;dr</h2>\n<p>Using Docker Compose we are able to quickly set up complex environments consisting of multiple containers, which allows to speed up software evaluation process.</p>\n<h2>Intro</h2>\n<p>Things evolving quickly, tools come and go, last year cutting edge is often legacy now. Dozens of new tools emerges every month\nand approach for being up to date also needs to evolve.</p>\n<p>Containers on production with all its benefits and challenges is a common thing nowadays, but do not forget that containers could also help us in other use cases. One of them is to improve technologies evaluation process. </p>\n<h2>Docker at home</h2>\n<p>Many moons ago when new fancy tool was released and looks so promising to give it a try options were limited - build it from sources, use installer or package manager. Giving a try for new promising tool was quite time consuming. Steps required to download, install, configure system and dependencies were usually not most exciting part of evaluating new message broker or database. Now containers or PaaS solutions allow us to shift focus directly from setup to features that particular products offers.</p>\n<h2>Level 1: Basic usage</h2>\n<p>Using Docker one terminal command is enough to download, run and evaluate interesting applications.</p>\n<div class=\"gatsby-highlight\" data-language=\"shell\"><pre class=\"language-shell\"><code class=\"language-shell\">docker run postgres</code></pre></div>\n<p>Above example command will pull latest version of <a href=\"https://hub.docker.com/_/postgres\">PostgreSQL</a> image from <a href=\"https://hub.docker.com\">Docker Hub</a> and run it locally. This is a quick and straightforward way of running hundreds of interesting applications. Container will run in sandbox environment, so we do not need to think about operation system settings and other specific configuration that may be required with standard installation. Although it is a simpler way than using installers or building from sources, then comparing to common package managers where also one command is usually enough, user experience looks quite similar.</p>\n<h2>Level 2: Next step</h2>\n<p>The real benefits of using Docker in local environment we can observe if we would like to build some complex environment that contains multiple applications linked together as usually things are more complicated than just running a database or monitoring tool separately. Challenge often starts when we would like to evaluate a monitoring tool that needs a datasource and entire environment should be relatively easily to set up and manage. That is where <code class=\"language-text\">Docker Compose</code> comes to help. </p>\n<p>As stated in <a href=\"https://docs.docker.com/compose\">official documentation</a> Compose is a tool that allow us to define and run multi-container applications. Using it in most common scenarios comes down to creating YAML file with required images and configurations. </p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">version</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'3'</span>\n<span class=\"token key atrule\">services</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">myService1</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">image</span><span class=\"token punctuation\">:</span> service1\n    <span class=\"token punctuation\">{</span>configuration<span class=\"token punctuation\">:</span><span class=\"token punctuation\">}</span>\n  <span class=\"token key atrule\">myService2</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">image</span><span class=\"token punctuation\">:</span> service2\n    <span class=\"token punctuation\">{</span>configuration<span class=\"token punctuation\">:</span><span class=\"token punctuation\">}</span></code></pre></div>\n<p>Having <code class=\"language-text\">docker-compose.yml</code> file ready we are able to start it with one terminal command.</p>\n<div class=\"gatsby-highlight\" data-language=\"shell\"><pre class=\"language-shell\"><code class=\"language-shell\">docker-compose up</code></pre></div>\n<p>Docker will build or download all necessary images, set up necessary configurations, networks and run defined containers for us.</p>\n<h2>Level 3: Hands-on experience</h2>\n<p> In below example we would like to see in action <a href=\"https://hub.docker.com/r/grafana/grafana\">Grafana</a> - open source monitoring tool with <a href=\"https://hub.docker.com/_/postgres\">PostgreSQL</a> as datasource. </p>\n<h3>Define PostgreSQL</h3>\n<p>First thing w need to do is to create empty <code class=\"language-text\">docker-compose.yml</code> file and add PostgreSQL as datasource.</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">version</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'3'</span>\n<span class=\"token key atrule\">services</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">myDatasource</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">image</span><span class=\"token punctuation\">:</span> postgres</code></pre></div>\n<p>Above we have defined one service called <code class=\"language-text\">myDatasource</code> that will be created using <code class=\"language-text\">postgres</code> image.</p>\n<h3>Define Grafana</h3>\n<p>Having our datasource configured we can extend our Compose file with second service - Grafana.</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">version</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'3'</span>\n<span class=\"token key atrule\">services</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">myDatasource</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">image</span><span class=\"token punctuation\">:</span> postgres\n  <span class=\"token key atrule\">myMonitoring</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">image</span><span class=\"token punctuation\">:</span> grafana/grafana\n    <span class=\"token key atrule\">ports</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> 3000<span class=\"token punctuation\">:</span><span class=\"token number\">3000</span></code></pre></div>\n<p>Above we have defined second service called <code class=\"language-text\">myMonitoring</code> that will be created using <code class=\"language-text\">grafana/grafana</code> image.\nAdditionaly to basic service definition we have also exposed port 3000, so Grafana user interface can be access from outside the container.</p>\n<h3>Troubleshooting</h3>\n<p>At this point we have configured our environment, so by running <code class=\"language-text\">docker-compose up</code> two containers should be configured and run by Docker.\nThen navigating to <code class=\"language-text\">localhost:3000</code> will allow us to access Grafana web interface where datasource could be set up.\nThing that is worth notice is that if we would like to configure our PostgreSQL datasource with default suggested <code class=\"language-text\">Host - localhost:5432</code></p>\n<p><a\n    class=\"gatsby-resp-image-link\"\n    href=\"/static/0dbbf0ff0acaaaf0a5714c155ad1d684/72b46/DatasourceConfig.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 448px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 45.53571428571428%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsSAAALEgHS3X78AAABiElEQVQoz32SWVPCQBCEeUCOQCABckIqJzfIES3EAqEU5ZLy//+admYDllrKw1fJZnd6ejuTWixX2B+OgtPpA4vlGpvXHd62exyP7xjejlDTDBimDd2wrqLpJlJhs4P4bobb0RSd7gCeF8LzQwRhk4hg1x2olRoqV+D9ak0Xoqlmq4+H+RNM24XjNqmLBUVRoapVQbWqoVgsQZKK/5LPF1Aqq+IWqSBsYxLP6GpT+PRumHXqmghdREslBbJc/oIb/F4rSiVx2O4O8bzZYbXeIIi69LEuxAzDpGto0DRdFGUyOQG7KRRk8fxO+eIwavUwntxTVh68IHHIrlgkKZTQcHw8LtaC/nBCZ12RXY1yu0TCNcJhGHXoh8RUFMD1W0JQoW4sxsh02LQaGFFTjiY4x8Ji/FdZkCPhBkJwQNm9bA7Y7k/oDcbQ6fBoHGM2myPwI2SzeeRyEtLpGyIDnUbIsmyKwxCCzI+xqTdcchbBpXFpOB5t2JSfRa4SF+p5LCrkhOGZ/Evosv4E7kLsTTjvj+sAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n    ></span>\n    <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;box-shadow:inset 0px 0px 0px 400px white;\"\n        alt=\"Datasource Config\"\n        title=\"\"\n        src=\"/static/0dbbf0ff0acaaaf0a5714c155ad1d684/72b46/DatasourceConfig.png\"\n        srcset=\"/static/0dbbf0ff0acaaaf0a5714c155ad1d684/762ef/DatasourceConfig.png 148w,\n/static/0dbbf0ff0acaaaf0a5714c155ad1d684/c91c8/DatasourceConfig.png 295w,\n/static/0dbbf0ff0acaaaf0a5714c155ad1d684/72b46/DatasourceConfig.png 448w\"\n        sizes=\"(max-width: 448px) 100vw, 448px\"\n      />\n  </span>\n  </a></p>\n<p>We will end up with following error message:</p>\n<div class=\"gatsby-highlight\" data-language=\"markdown\"><pre class=\"language-markdown\"><code class=\"language-markdown\">dial tcp 127.0.0.1:5432: connect: connection refused</code></pre></div>\n<p>This is happening because Compose creates network for our application and inter container communication happens via services names.\nIn our example using <code class=\"language-text\">myDatasource:5432</code> as <code class=\"language-text\">Host</code> solves connection issue.</p>\n<h2>Further explorations</h2>\n<p>This relatively simple example consisting of two containers can be considered as a base for further journeys in world of containers.\nPublic cloud providers offers multiple services like <a href=\"https://aws.amazon.com/ecs\">Amazon Elastic Container Service</a> or <a href=\"https://azure.microsoft.com/en-us/services/kubernetes-service\">Azure Kubernetes Service</a>\nwhich can be utilised as next step in building container based environments.</p>","fields":{"slug":"/exploring-technologies-with-docker/","tags":["docker","compose","grafana"]}}},{"node":{"id":"2b607647-03dd-50d4-8f72-310a92d54e79","frontmatter":{"category":"Coding","title":"Yet another story about a monolith and microservices","date":"2018-12-04","summary":null,"thumbnail":{"relativePath":"pages/vigolante/square-gopher.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAABpklEQVQoz32SS0sCURiG/Qn9gH5BUHtXLWsXbdto3h3NQAMpESpoExIpVJDUpiBwEQTSBa3UURscrzM6F8PLjKMJujBRy0vZqCVi6uHjnMPH+/Ce9+NwACzTKwXOCJG02OnXunxyd0gUpZREtrO7/Me+sAkKST0ROZHt69ni9A4lS6LUAYxUarVGvf6Wz++BPn6U1kPhYrHYZler6SPiIi+iIHMARg/CtAxn1oPklcVybjZ/d7RtNJHkeSKn1jsJn4eTJNtpVCu7ICwmcorYIByjJbHMFprUqNVcLrfLthMUxQY5urevLC/hBMF2PsvvehCWkENwN7AISV24oWqh0P5qtT5qhueXWe3O4uZ2MEm1ms1yqXQJBYSBuGIgNqd/k+OMJEDuQ+GzIKoDYY3ZNDM9tTA/p7u51jhglRMWhBLAyIH9+hNZMc7w8ZzQG4nbjZHbQwY8cVuNgnASeM2zrxsUD8MdHqPXsIwwShsebKjHBYJO1aMLwBjgL+ckuDc/GZHbgHGTzWF4cstZ8p/neLjjn5HG6FUkLUBSIwWT4P7PUY7x7NUPicXZxAqt2owAAAAASUVORK5CYII=","width":570,"height":325,"src":"/static/dc7ba27f8138dca1c3ae8defbfbb334d/b3029/square-gopher.png","srcSet":"/static/dc7ba27f8138dca1c3ae8defbfbb334d/b3029/square-gopher.png 1x"}}},"authorName":"Dmytro Malyshenko","authorDescription":"Team Lead Software Engineer","authorAvatar":null,"headerImage":{"relativePath":"pages/vigolante/golang-banner.jpg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAFABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAIE/8QAFQEBAQAAAAAAAAAAAAAAAAAAAQT/2gAMAwEAAhADEAAAAdNFEwD/AP/EABcQAQADAAAAAAAAAAAAAAAAAAABESH/2gAIAQEAAQUCRi3/xAAVEQEBAAAAAAAAAAAAAAAAAAAAEf/aAAgBAwEBPwFX/8QAFREBAQAAAAAAAAAAAAAAAAAAABH/2gAIAQIBAT8BR//EABQQAQAAAAAAAAAAAAAAAAAAABD/2gAIAQEABj8Cf//EABgQAQADAQAAAAAAAAAAAAAAAAEAESFR/9oACAEBAAE/IYrWRWHMn//aAAwDAQACAAMAAAAQg+//xAAWEQEBAQAAAAAAAAAAAAAAAAABABH/2gAIAQMBAT8QHGVt/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQAR/9oACAECAQE/EE0gZf/EABgQAQEBAQEAAAAAAAAAAAAAAAERACEx/9oACAEBAAE/EM/EsTpfcEVGYUK7/9k=","width":1280,"height":333,"src":"/static/b2168e9dcfd879a80bb3db0d5b429775/966a5/golang-banner.jpg","srcSet":"/static/b2168e9dcfd879a80bb3db0d5b429775/966a5/golang-banner.jpg 1x,\n/static/b2168e9dcfd879a80bb3db0d5b429775/aa36d/golang-banner.jpg 1.5x"}}}},"html":"<p><strong>The story about how one hackathon project sped up the development of our back office system by 2 days per feature. The story about how we enabled our teams to develop in the newest technology-agnostic stack by extending the architecture of legacy monolith application. The story about how we enabled our teams to extend a monolith back office without touching it.</strong></p>\n<h3>Once upon a time, there was a startup which was built as a monolith...</h3>\n<p>In AUTO1, as in the majority of other companies, we also have a back-office software (aka “Admin”) where our employers can manage our business operations. We’ve got a lot of business processes, and therefore a lot of business logic put into the code.</p>\n<p>A couple of facts about Admin:</p>\n<ul>\n<li>it's a web-based software, built with PHP</li>\n<li>the first commit dates back to 1st of Aug, 2013, by the current VP of Engineering</li>\n<li>it was built on the Silex framework, using ORM (doctrine) with direct connection to MySQL</li>\n<li>32.5k commits</li>\n<li>~100 contributors</li>\n<li>~600k lines of code</li>\n<li>at some point in time, we had 4 teams dedicated only to Admin</li>\n</ul>\n<p>From these facts, you can see, that what the thing we’re talking about - it's a typical monolith.</p>\n<p>An authentication between requests was handled with a very common approach for PHP applications - <a href=\"http://php.net/manual/en/book.session.php\">PHP Sessions</a>. With this approach the session identifier for the current user is put in a cookie, and on the server side, the session data is somehow stored as a document.</p>\n<p><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAugAAAGACAYAAAD/FZc6AAAgAElEQVR4XuydBZgUxxaFz7rg7oEEh/ACRIDggUBwgkNwdwmeYAGCu7u7u5MACYQkBAgQ3F2XxdblfbdmZ1ZYmZXp7Zk9lfDNznR1ddV/q7tP3759287zrXcwWEiABEiABEiABEiABEiABHRBwI4CXRd2YCdIgARIgARIgARIgARIQBGgQOdEIAESIAESIAESIAESIAEdEaBA15Ex2BUSIAESIAESIAESIAESoEDnHCABEiABEiABEiABEiABHRGgQNeRMdgVEiABEiABEiABEiABEqBA5xwgARIgARIgARIgARIgAR0RoEDXkTHYFRIgARIgARIgARIgARKgQOccIAESIAESIAESIAESIAEdEaBA15Ex2BUSIAESIAESIAESIAESoEDnHCABEiABEiABEiABEiABHRGgQNeRMdgVEiABEiABEiABEiABEqBA5xwgARIgARIgARIgARIgAR0RoEDXkTHYFRIgARIgARIgARIgARKgQOccIAESIAESIAESIAESIAEdEaBA15Ex2BUSIAESIAESIAESIAESoEDnHCABEiABEiABEiABEiABHRGgQNeRMdgVEiABEiABEiABEiABEqBA5xwgARIgARIgARIgARIgAR0RoEDXkTHYFRIgARIgARIgARIgARKgQOccIAESIAESIAESIAESIAEdEaBA15Ex2BUSIAESIAESIAESIAESoEDnHCABEiABEiABEiABEiABHRGgQNeRMdgVEiABEiABEiABEiABEqBA5xwgARIgARIgARIgARIgAR0RoEDXkTHYFRIgARIgARIgARIgARKgQOccIAESIAESIAESIAESIAEdEaBA15Ex2BUSIAESIAESIAESIAESoEDnHCABEiABEiABEiABEiABHRGgQNeRMWLTlTdv32HZ6vX45bcT8PB4iUwZMuCbyhXQomkDODk6xqYps+p27j0Qbm5umDp2RJT1Z85fgnWbd+DY3i1wcLA3q11WIgESIAESIAESIAESCE+AAt0KZ4S/vz869xmMi5evomypL5Dzg+y4fPU6Tp05hy9LfIZJo4fCzs4uQUfWoUc/JdBnTBgVZbt7DvyC3/74Cz8PHQB7ewr0BDUAGyMBEiABEiABEkgyBCjQrdDU23btw/hpc9CvZ2fU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\" alt=\"Monolith PHP Application\"></p>\n<h3>The moment any monolith is afraid of</h3>\n<p>Then we’ve got our first microservices. Some business logic started to live its own life. And of course, our Admin should have had some control over it. So our Admin started to interact with our microservices, and initially it was treated more or less as a third-party API.</p>\n<p><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAugAAAKgCAYAAADJUYiRAAAgAElEQVR4XuydCbxNVfvHf+5w7mxWhqSISoNSSiHNRSVlJkmGyJCMCU00ERlC5nnOXFQoSSV5iZAMhTJmuK47j+/nWbd9nHuce++Zz977/Pb77+86Z+21nvV91rl++znPelaR+MSUHPAiARIgARIgARIgARIgARLQBYEiFOi68AONIAESIAESIAESIAESIAFFgAKdC4EESIAESIAESIAESIAEdESAAl1HzqApJEACJEACJEACJEACJECBzjVAAiRAAiRAAiRAAiRAAjoiQIGuI2fQFBIgARIgARIgARIgARKgQOcaIAESIAESIAESIAESIAEdEaBA15EzaAoJkAAJkAAJkAAJkAAJUKBzDZAACZAACZAACZAACZCAjghQoOvIGTSFBEiABEiABEiABEiABCjQuQZIgARIgARIgARIgARIQEcEKNB15AyaQgIkQAIkQAIkQAIkQAIU6FwDJEACJEACJEACJEACJKAjAhToOnIGTSEBEiABEiABEiABEiABCnSuARIgARIgARIgARIgARLQEQEKdB05g6aQAAmQAAmQAAmQAAmQAAU61wAJkAAJkAAJkAAJkAAJ6IgABbqOnEFTSIAESIAESIAESIAESIACnWuABEiABEiABEiABEiABHREgAJdR86gKSRAAiRAAiRAAiRAAiRAgc41QAIkQAIkQAIkQAIkQAI6IkCBriNn0BQSIAESIAESIAESIAESoEDnGiABEiABEiABEnCbQE5Ojsv3FilSxOV7eAMJBBMBCvRg8jbnSgIkQAIkQAIuEHBFfDvbtjBxXtj7LpjPpiRgWAIU6IZ1HQ0nARIgARIgAe8ScCSy5TURzeFhoQgNCUFISBFI/FsT0hIMl1e0oHh+Ajs30J6D7JwcyM/yZ1ZWDrKys5CZlQ1tHPsZUbB718fszRgEKNCN4SdaSQIkQAIkQAI+IWAvyuXvYaGhsISFIiz0P0Hup5QUEe3Z2TlIy8xEenqmmq+tQKdY98kSYKc6JECBrkOn0CQSIAESIAES8CUBW1EuP4eEhCAiPEwJcomS+0mPFzpFEetZ2dlIzchEZmYWxXqhxNjALAQo0M3iSc6DBEiABEiABAogYC/KRYhHRYQrUW6EyLSkxYhYT0nLQGYWxToXu7kJUKCb27+c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sS1iPe/aqiFcXZx10T42ggRIgASskQAFujWOKvtEAiRAAglAIDLreakvPkO5Ul8kQOksggRIgARIICoCFOicGyRAAiRAApESOHzibxyj9ZyzgwRIgAQ0J0CBrjlyVkgCJEAC+icQqfW82GcoV5LWc/2PHltIAiRg6QQo0C19BNl+EiABEjADgT//OoOjp/4xlkzfczNAZpEkQAIkEAUBCnRODRIgARIggXAEIrOef1XsM3xN6zlnCgmQAAloQoACXRPMrIQESIAELIfAnyfP4ujJc7SeW86QsaUkQAJWRoAC3coGlN0hARIggfgQiMx6XvrLz1G2RNH4FMt9SYAESIAEYkGAAj0WsJiVBEiABKydwJGT53Dk5Flaz619oNk/EiABXROgQNf18LBxJEACJKAdAV9fP/XWUB9fX2OlpYsXRtniRbRrBGsiARIgARIABTonAQmQAAmQgCJA6zknAgmQAAnogwAFuj7Gga0gARIggUQlEJn1vEzxwihD63mijgsrJwESsE0CFOi2Oe7sNQmQAAmEIyAxzyX2uSG5ODuhc8sGcHVxJikSIAESIAGNCVCgawyc1ZEACZCA3ghEbj0vArGgM5EACZAACWhPgAJde+askQRIgAR0ReDYqX9wOIL1vGurhnB2dtJVO9kYEiABErAVAhTotjLS7CcJkAAJREKA1nNOCxIgARLQHwEKdP2NCVtEAiRAApoRuH77HtZv32+sT3zPaT3XDD8rIgESIIFICVCgW+jEePvuPRavWIPf/zyGly9fIUO6dPimUnk0b1wPTo6OCd6rTr0GwM3NDZPGDI+y7GlzFmL1hq04vGsjHBzsE7wNLJAESCDhCVy7dRcbdhwwFlyu1Bco9cVnCV8RSyQBEiABEjCZAAW6yaj0k9HPzw+deg/CxctXUbZUcWT/KCsuX72O02f/xVclimHCqCGws7NL0Aa3795XCfSpv46Mstyde3/Hn8dP4pch/WFvT4GeoAPAwkjAjAQOnTiD46f/QfasmdC49jdmrIlFkwAJkAAJmEKAAt0USjrLs3n7boybPBN9e3TC97WqG1s3cfpcrN+yA3Mmj0OhT/InaKtNEegJWiELIwESIAESIAESIAEbJUCBboED32vgMFy8cg27NywPZ6n28/fH48dPkS1r5gTvFQV6giNlgSRAAiRAAiRAAiQQKQEKdAucGPVa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\" alt=\"First microservices\"></p>\n<p>Our microservices are located behind an API gateway (we call it GateKeeper), every authenticated request should be signed with an OAuth token to get through it. Also, every request should be signed by the client application with an API key.</p>\n<p>Admin has become one of the external clients of microservices API. It had its own API key, every user was obtaining an OAuth token, which is kept in a session document, as a part of a session data.</p>\n<p>Months were passing. In general, an architecture stayed the same, apart from the fact the number of our microservices increased. And increased a lot.</p>\n<p><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABCwAAAL6CAYAAAD9pceYAAAgAElEQVR4XuydC5xM9f//X2ZvMzu7a1m+hURK35IovpWKdFNJF13oIpUvklwq0pVv9aX6dlOIIkREJbcQJV18VX7lryKSy9clkiJr7zO7s/t/vI/ONDt27Zwz58w5Z+Z1euxjs/O5vD/P92dmzud13p/3p1ZuQXEFeJEACZAACZAACZAACZAACZAACZAACZCAjQjUomBhI2/QFBIgARIgARIgARIgARIgARIgARIgAYUABQtOBBIgARIgARIgARIgARIgARIgARIgAdsRoGBhO5fQIBIgARIgARIgARIgARIgARIgARIgAQoWnAMkQAIkQAIkQAIkQAIkQAIkQAIkQAK2I0DBwnYuoUEkQAIkQAIkQAIkQAIkQAIkQAIkQAIULDgHSIAESIAESIAESIAESIAESIAESIAEbEeAgoXtXEKDSIAESIAESIAESIAESIAESIAESIAEKFhwDpAACZAACZAACZAACZAACZAACZAACdiOAAUL27mEBpEACZAACZAACZAACZAACZAACZAACVCw4BwgARIgARIgARIgARIgARIgARIgARKwHQEKFrZzCQ0iARIgARIgARIgARIgARIgARIgARKgYME5QAIkQAIkQAIkQAIkQAIkQAIkQAIkYDsCFCxs5xIaRAIkQAIkQAIkQAIkQAIkQAIkQAIkQMGCc4AESIAESIAESIAESIAESIAESIAESMB2BChY2M4lNIgESIAESIAESIAESIAESIAESIAESICCBecACZAACZAACZAACZAACZAACZAACZCA7QhQsLCdS2gQCZAACZAACZAACZAACZAACZAACZAABQvOARIgARIgARIgARIgARIgARIgARIgAdsRoGBhO5fQIBIgARIgARIgARIgARIgARIgARIgAQoWnAMkQAIkQAIkQAIkQAIkQAIkQAIkQAK2I0DBwnYuoUEkQAIkQAIkQAIkQAIkQAIkQAIkQAIULDgHSIAESIAESIAESIAEbE2goqJCs321atXSXIcVSIAESIAE7EWAgoW9/EFrSIAESIAESIAESCBhCRxNmIhUtKhJqKjp9YSFz4GTAAmQgA0JULCwoVNoEgmQAAmQAAmQAAnEO4GqBAj1b6mpyUh2ueByuSBxEq5atXA4YEL9fSSdw0EYFZBf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r2PHTUKFx8qiXp2aSExMxLcHDsNHo8GaxXPkla8ULOz7s8fRSIAESIAESIAE1EOAgoV6fEFLSIAESCATgbj4BKxYuxH7Dx3BvYj7KBAWipo1qqF7xzb6wpp/nr+I7v2H4f1hA/FWw1ezEBRCxFttu+KlmtUxZsS78v3d33yHZWs2IDIyCk8+8ThefeUljJ80E0vnTkPFCo/JNuLKzg/GfQ5RB6NFk8YQ9R+EiFK3UUt5M0enti30cwnR4Mdjv2DbuqU5elBEcoiIjq1rF8vrNw0fIVCsWPMVrl2/jvyhoWj42svo0bm9PJSLR6kNYSisREVFo12PAXjyiQr6VArBRERanD13EUGBAahYsTy6d2gjD/3iEeuo17gV+nbvlO06lCiXaRM/wosvPGd2baKY5tffHUTxYsX0N4CkpaVj6ep12P31fkRERqFk8WLo0KZFpnobC5euwuqNW3Bo9yb92MdPnpa3n4ibPZRrYkWB1VXrNuGf6zfkdadPP1UJ/bp3koKVOS7idZE6VKlC+SyFPHN0EhuQAAmQAAmQAAmQgEoIULBQiSNoBgmQAAmQAAmQAAmQAAmQAAmQAAmQwH8EKFhwN5AACZAACZAACZAACZAACZAACZAACaiOAAUL1bmEBpEACZAACZAACZAACZAACZAACZAACVCw4B4gARIgARIgARIgARIgARIgARIgARJQHQEKFqpzCQ0iARIgARIgARIgARIgARIgARIgARKgYME9QAIkQAIkQAIkQAIkQAIkQAIkQAIkoDoCFCxU5xIaRAIkQAIkQAIkQAIkQAIkQAIkQAIkQMGCe4AESIAESIAESIAESIAESIAESIAESEB1BChYqM4lNIgESIAESIAESIAESIAESIAESIAESICCBfcACZAACZAACZAACZAACZAACZAACZCA6ghQsFCdS2gQCZAACZAACZAACZAACZAACZAACZAABQvuARIgARIgAT2By39fRafeg9Dw1ZcxduTgLGRO/fEn+g4elel1fz8/lC5VEm1aNEHDBvX07w0aORZ37kVg3ZK5Zgmba3Pm3Hn0H/YBateohvFjM8+X1+5auHQVVm/cgkO7N+X1VByfBEiABEiABEiABEggGwIULLg9SIAESIAE9AQWLF2JZas3IiBAiz1frYKvryYTnROn/kD/Ye/jpVo1UL7co/K9+IQE/Hz8N/x1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JeQ9EwmQAAmQAAkYQoCChSGUmIcESIAESIAESIAESIAESIAESIAESCBJCVCwSFLcbIwESIAESIAESIAESIAESIAESIAESMAQAhQsDKHEPCRAAiRAAiRAAiRAAiRAAiRAAiRAAklKgIJFkuJmYyRAAiRAAiRAAiRAAiRAAiRAAiRAAoYQoGBhCCXmIQESIAESIAESIAESIAESIAESIAESSFICFCySFDcbIwEScEQC569cx69/nFJDL1O8KArkzumIGDhmEiABEiABEiABEiABEjCKAAULo3AxMwmQAAkYT2Deyk3wf/ZcFUyVMgU6fF3P+ErsuIQc87h59y8IDw9Hw5qVIEcgMpEACZAACZAACZAACZAABQvOARIgARIwM4FxPy2O1sLAbm3M3KJtVb/v8HGcPHNedfrjwgVQqWwJ2xoAe0sCJEACJEACJEACJGAWAhQszIKVlZIACZDAWwIULGKfDf9duobt+w5Hy1CzclkUyvsBpxAJkAAJkAAJkAAJkICDE6Bg4eATgMMnARIwPwEKFjEzfvTUH0vXbUdEeAQQZRuIi4szWjWqiXSpU5nfOGyBBEiABEiABEiABEjAaglQsLBa07BjJEAC9kKAgsX7lgwKDsHitVvx4uVrQKuNJlhI7uTJfNC2SR14erjbyzTgOEiABEiABEiABEiABIwkQMHCSGDMTgIkQALGEqBgEZ2YVqvFqi27cfvuQyVWaJ2coAuzqQX073NkyYTGtSvDiUE4jZ1yzE8CJEACJEACJEACdkGAgoVdmJGDIAESsGYCFCyiW+fnYyfw56mzgBbQOmnxVq54k088LkS2cAJKfvw/lC35sTWbl30jARIgARIgARIgARIwEwEKFmYCy2pJgARIQEeAgsXbuXDlxm1s2HHAqMnRpHYV5MiayagyzEwCJEACJEACJEACJGD7BChY2L4NOQISIAErJ0DB4q2BLl65gc17fjHKYpW/KIFi/ytgVBlmJgESIAESIAESIAESsH0CFCxs34YcAQmQgJUToGARt4HIx8onMLtHAiRAAiRAAiRAAhYiQMHCQuDZLAmQgOMQ4IKcgoXjzHaOlARIgARIgARIgARMR4CChelYsiYSIAESiJEABQsKFnw0SIAESIAESIAESIAEjCdAwcJ4ZixBAiRAAkYRoGBBwcKoCcPMJEACJEACJEACJEACigAFC04E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\" alt=\"More microservices\"></p>\n<p>More and more business logic was covered by services while less and less logic was implemented in Admin. Then at some point were realized, that what happens in Admin - it’s just a proxying of requests to a gateway. The usual code for a new feature was more or less - send a request to the Gateway, get a request, send this request to a front-end client. Not the most exciting engineering work ever. </p>\n<p>Moreover, we’ve got another complication - some teams without any PHP engineer had to add some new features to back-office. For this, one needed to create a proxying code, and for this one would need some support from another team.</p>\n<h3>There should be a better way</h3>\n<p>So we’ve started to think of possibilities to send requests to the Gateway directly from Frontend, in order to avoid a necessity to make any implementation in Admin every time we do a new feature.\nAnd challenges were:</p>\n<ul>\n<li>we can't get rid of Admin. Even though it was getting almost no new features, there were a lot of old ones. And usually, we were adding new widgets into old pages.</li>\n<li>we can’t get rid of sessions - our old Admin features depend on them</li>\n<li>we don’t want to keep two mechanisms of authentication on a Frontend side.  I.e. we don’t want to introduce anything alongside sessions, in order to avoid consistency issues between the user session and our permissions model.</li>\n</ul>\n<p>Then unexpectedly a group of our engineers (Mikhail, Oleg, Alexey and Andy - thank you, guys!) came out with a prototype of Vigolante, as a <a href=\"https://auto1.tech/one-more-hackathon-at-auto1/\">Hackathons</a> project.</p>\n<p><em>Vigolante - a mix of GO and VIGILANTE (sp.), which means a guard.</em></p>\n<p><img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABVgAAAIgCAYAAABwLALzAAAgAElEQVR4XuzdBVhU294G8JdQAVuxu8EuLDCx69hioZjYefXoMY8eu7uxUOxusbHwmCAIdrfYQd1nLc9sQQYdcAZmhnc/3/fce4a11/6v39p4n/O6Zi2ToPefwsGLAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoAAFYixgwoA1xma8gQIUoAAFKEABClCAAhSgAAUoQAEKUIACFKCAFGDAyheBAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoEAsBRiwxhKOt1GAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUYMDKd4ACFKAABShAAQpQgAIUoAAFKEABClCAAhSgQCwFGLDGEo63UYACFKAABShAAQpQgAIUoAAFKEABClCAAhRgwMp3gAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKBALAUYsMYSjrdRgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFGDAyneAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoEAsBRiwxhKOt1GAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUYMDKd4ACFKAABShAAQpQgAIUoAAFKEABClCAAhSgQCwFGLDGEo63UYACFKAABShAAQpQgAIUoAAFKEABClCAAhRgwMp3gAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKBALAUYsMYSjrdRgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFGDAyneAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoEAsBRiwxhKOt1GAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUYMDKd4ACFKAABShAAQpQgAIUoAAFKEABClCAAhSgQCwFGLDGEo63UYACFKAABShAAQpQgAIUoAAFKEABClCAAhRgwMp3gAIUoAAFKEABClCAAhSgAAUoQAEKUIACFKBALAUYsMYSjrdRgAIUoAAFKEABClCAAhSgAAUoQAEKUIACFGDAyneAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUoEAsBRiwxhKOt1GAAhSgAAUoQAEKUIACFKAABShAAQpQgAIUYMDKd4ACFKAABShAAQpQgAIUoAAFKEABClCAAhSgQCwFGLDGEo63UYACFKDAzwXeffyMZy+D8PlLMMLCw8mVAAVMTUxgkSQR0qdNheRWFglQgEOmAAUoQAEKUIACFKAABRKCAAPWhDDLHCMFKECBOBYQ4eqdh8/i+Kl8nD4L5MySniGrPk8Qa6MABShAAQpQgAIUoAAFYi3AgDXWdLyRAhSgAAWiE7h5/wk+fv4K61TJkCOTNSyTJCZWAhT49OUr7j5+gRdB72FpkRh5s2VMgAocMgUoQAEKUIACFKAABShg7AIMWI19hjk+ClCAAvEg4HPjPsLDw1HSJiesLBiuxsMU6M0jRdB+wf8OzExNUDBPNr2pi4VQgAIUoAAFKEABClCAAhTQlgADVm1Jsh8KUIACFFAErgbek//doXh+qlAAJy8FSIUi+bJTgwIUoAAFKEABClCAAhSggNEJMGA1uinlgChAAQrEvwAD1vifA32qgAGrPs0Ga6EABShAAQpQgAIUoAAFtC3AgFXbouyPAhSgAAXAgJUvQUQBBqx8HyhAAQpQgAIUoAAFKEABYxZgwGrMs8uxUYACFIgnAQas8QSvp49lwKqnE8OyKEABClCAAhSgAAUoQAGtCDBg1QojO6EABShAgYgCDFj5PkQUYMDK94ECFKAABShAAQpQgAIUMGYBBqzGPLscGwUoQIF4EmDAGk/wevpYBqx6OjEsiwIUoAAFKEABClCAAhTQigADVq0wshMKUIACFIgowICV70NEAQasfB8oQAEKUIACFKAABShAAWMWYMBqzLPLsVGAAhSIJwEGrPEEr6ePZcCqpxPDsihAAQpQgAIUoAAFKEABrQgwYNUKIzuhAAUoQIGIAgxY+T5EFGDAyveBAhSgAAUoQAEKUIACFDBmAQasxjy7HBsFKECBeBJgwBpP8Hr6WAasejoxLIsCFKAABShAAQpQgAIU0IoAA1atMLITClCAAhSIKMCAle9DRAEGrHwfKEABClCAAhSgAAUoQAFjFmDAasyzy7FRgAIUiCcBBqzxBK+nj2XAqqcTw7IoQAEKUIACFKAABShAAa0IMGDVCiM7oQAFKECBiAIMWPk+RBRgwMr3gQIUoAAFKEABClCAAhQwZgEGrMY8uxwbBShAgXgSYMAaT/B6+lgGrHo6MSyLAhSgAAUoQAEKUIACFNCKAANWrTBG7eTDx49Ys34zPI964enz50iTJjXKlS4Jl7YtkN7aWrnhso8fXPsNibaKHp3bI1PG9BgxbspPK+3k3AqdnVtFaXP+4hX0/t9wLJ07BYVsCuhotLrrtmvfwShayBa9urpEeci5fy9iwLAx2LdlLZIltYpREbMXLse+Q0fx4eMHHNuzWd4bFPQGY6fMwqUrPihdsjgmjRmGQ0dPSHu3+dNhkz9vjJ6haeN37z+gYcsO+GfkEFQoW1rT2zRqJ97D6g2dEN37octnR1dgx54DkT6dNSaOHqrRGGLSyOuMNwYNH4t508ajZLHCMbmVbbUswIBVy6AG3h0DVgOfQJZPAQpQgAIUoAAFKEABCvxUgAGrDl6Qr1+D0WPAMPj6X0f5MqWQK0c2BN68jUtXfJE6VUosnjMZGdKlk0++cNkHPQcOQyX7csiXJ1eUasqWKoGkSa1w+LiX8rO9Bw/jzZt3cGr2h/JZqeJFUaJooSj3n/G+gP5DR2PhzEkoVtg22tGKoHeF+3oM/18fpE2TRmm3ecce+F7zx8g/B+hA6uddPn/xEg2dXDB/+gS1Y5s4Yx4ePHyMuVPHxag27wuX0WfwCDiULwP7sqXRqH5tef/8pSuxZv0WtGjUABXKlUKZUiUgXNZu3Iq+rp2QOVOGGD1H08YHDh/HxOlzsXfzGiRJkljT2zRq9+XLV4yaMA3Vq1ZE9coOUe7R5bOjK9C5Wz+kT5cWU8eN0GgMMWl0PfAGlq/ZgG4ubZE7Z/aY3IrJs+YjS6ZMaNOicYzuY2P1AgxY+WZEFGDAyveBAhSgAAUoQAEKUIACFDBmAQasOpjdzdt3Y+qcRRjQqyuaN6qvPEGsrhs88h90bt8aLm1ayM9VAeuooQNQ27GKRtWIwPTO/QfYumbpL9trGrCqVmp6LJ+PHNmzKv2K0On4ybPYtXHlL5+l7QbCcdnq9di1YQVMTU0jdR8WFoaGLV3Qvk3zSMaa1OCxaRtmLVyOHR5uSGedVrll4LC/8ejpE6xbNl+TbrTW5q+/JyEsPBwTRv2ptT417Sg+nq3LgFXTcatr59SxB/LlzoWxw//3O93w3v8EGLDyVYgowICV7wMFKEABClCAAhSgAAUoYMwCDFh1MLt9h4zCtesB2L/FPUowKLYLUK1eFY/Wl4BVrGQcNX4q1i6bJ1fcqi6xSvS411ns2bRKB1I/77LP4JHImDE9hg3oFaXhFR8/dOs3BNvWLYvkqUmRS1auxfLVHji+bwsSmZsrt4jtCMzNzOSK2bi6xGrnOk3b4H/9emgcsGurtvh6tr4GrC06uCJ/nlwYNyL6LTu0ZZ8Q+mHAmhBmWfMxMmDV3IotKUABClCAAhSgAAUoQAHDE2DAqoM5a96+G8zMzCBWg/7qiquAdfj/+kKEqNf8r8PaOg1c2jihZrVKsjzV6lVVrWKvUbHnqFi9unXnPmUIrZs3Qu9uHREcHIwq9ZrLPV8fPH6Cs94XERwSjEoVyqJ/z66wsrSQ94SGhmHJSnfsO3gEr14HIVOmDBBbHji3agbrtN+2IRD7m3oeOwnPnethafHtPnG9e/cedZu1w6S//1K7L+ncxW4ynF4+b1okYvEV8flLV8PX7zoSJUqE8nYl0LNrB2Xbg6Wr1mHZqnXKPYkTJ5J7sHbpPQg+fgHK52LLBrEH6zGvM/hz1Hi4L52D3DlzyJ+/CgrC3EVuOON9ESYAihSxRd9uHZEp47ctBMS43dw9sGe/J14FvUGO7NnQsU0LVHYoH+V1OHX2PIaM/Ad7Nq1G8uTJlJ8fOe6FDVt34va9Bwj++hWZM2ZEW6emqOVYWWmz2G0N1m/diTFDB8LNfQNu37mHrJkzoVvHtrAvZyfbqebKtWM7tHNqGun50T1bNb7T5y7I+4sUspGGeXPlVO4X+wYnT54cRQraYPcBTwS9eQu7EkUxsFc3pE6dSmkXEHgTM+YvwfXAW9KnScM62L77QKQtAlRbNowdMRg7dh+A3/UAuadu0z/qo23LJpFqPnTsJFat3YR7Dx4gTaqUqF2jGjq2c5LBuLhUfS2ZMwWFbb/tOaxJrWL16t17D5Rnie0LVIZRJo0faCTAgFUjpgTTiAFrgplqDpQCFKAABShAAQpQgAIJUoABqw6mXewbmiVTBiyYMfGXvasC1ioVKyB/3tyR2heyySf3Af3xis0WASJIrF+7ulztuefgYRkmLZs7FQVt8uPt23fYsG0nlq3ykHutilV8eXLlwOMnTzFj3hJcvOqLKWNHIGOG9MiY3hpi5WPluk3l6s/ChWxkaHrteiCOe51BnRpVMXJIf1nyqnWbsGDZKohgtkC+vLh7/wH2HTqCgb27oUKZb4c5TZg+FydOncMW9yWwSJJEGeo+z6OYMmsB9m5aA1H7j5cIsevXqo72rZsrP3r89BnadumNFMmSolb1qnj/7gP2HjqMjOnTY+XiWTKEE/u6LnRbI8PPedP+kXueisO/bt25ixHjpsLM1BQD+7gidcoUyJ4tC0TQOezvSVi5aCby58ktw1OX7v3x4NFj1K3pKPfUFc8Q13q3hTAzM8W0OYsg9q5tVL+WDGWFizhsbNo/I+WevBGv8dPn4unT55g1aUykz0eMnYzESRKjsK2N/HzPQU9c8w/EmiVzlBXGYs/Y1R6bkTpVKhmWW1gkwd4Dh2WY7b50rqxfNVddXdoq21KoHqTu2arxPX/5Co3r14KVlRV27T8k+1y3bK4SVItA2i/gBnJlz45a1avg/sNH2Ln3oAzDVXurfvz0Gc3adcXXr19Rr6YjLCyTyLD9ddAblCldQmmn2sZCBOLVK9sjW7as0sw/4Ab+GtRHvrfiOnriFIaOmQjbAvlQsXwZ3Lh1R+5NLPbQHdKvh2yjbksMTWoNuHkLg4ePQ5bMmSCsxPsf04PTfvnLnsAaMGBNYBP+i+EyYOX7QAEKUIACFKAABShAAQoYswADVh3Mbt1mzrDNnxfTxo+UvYvwpn23fsqTTExMcHD7OiS1slK2CFBXRtOG9TCoT7coP4pNwCpW+XVp31r29eTZCzRp00ke5tOzSwf5WUz2YFWFdiKcXTxrsgwVxSVWYp45fwFHd2+CGKM4zf3e/YfYsHJhjJVFqGlmYgKxqvHHS4ShbTr3lnul5szxfb/YRW6rscZjC1YumqUccLR7vyfGTZmFKWOHy0OtxKVaxXpy/zaldvG5WOloKrYImDZeeeSPAevpc/9iwLAxGDqgFxrWrSnbvXnzFq+D3spaPn78hFqNW6NFkwZyta+4gkNCZCgrDg+LGKSKfWTrt+ggVwKLlZ0/u0R43KRNZwwf3FeGleJSBayTxw6XgaN81wJvon33/ujeyVmuFI4uYI3u2aqAMuIKThG0ixWeHds6KYG2CC3vPniEzauXIHmypPLZIizfsecADu/aIFcjnzx9Dv8bMU6G9nWqf9tfWFWfWB2qCmJVzxSHtonDxMT14eNHtO7YE7lyZsfMid/CZ7ElhAh6Vy2apax2Hjt5JvYdOop9W9xlHdEFrL+qVfTPPVhj/Gv60xsYsGrX09B7Y8Bq6DPI+ilAAQpQgAIUoAAFKECBnwkwYNXB+9GoVUekT28tw0dxiRWinse85H8/ePQ4Ll72wfG9m+VX2FUrWMWqT7H6U5MrNgHrnCnjULpEUaX7P5xcUKxIIfz91yD5WWwC1mZ/1JOrUVWXx5YdmDV/qTwQK23q1BCB5wr3jXLrgBJFCyFrlswoWsgWKVIk/+kwxcn3dZu1xdCBvVG9SsUobcXX4fd7Ho2yBYMIZW/cvB0p0H39Ogh1mzujj2tHtGrWSPb1OwGrWOk7Y+6SKAdkqYq8efuuXEXbr3sn6au6Vq7bhJu37kSq7bKPnwx1d65foWyZEHGwn798katbP33+jC9fg2Xbvj06w6lJQ9lMFbDu27wGKVOmUG6t0agValStiMF9e0QbsEb37I3bdmH63MVyH1pLi+8riof+PRFlShaXwbK4RMCaKHHiSGH0zj0HIFbFrndbIFfPbtq+W67m/fEwsVpN2sitBX4MWMePHIKqleyVcQwZNV6uelZttVG7aVtUti+n1CAaeh49ieHjJmPFgulylXR0AeuvahV9MWDV5E8fzdswYNXcKiG0ZMCaEGaZY6QABShAAQpQgAIUoEDCFWDAqoO5b+nSHeHh4diwIurKTfHVbxGq7v7v0Ki42oN14cxJKFbYVhmt+Iq9Tb68yonpsQlYXdq2RNcObZQ+93sew+gJ05Sv04uAcJHbGhw7cQqPnz6X7cT+rGOHD1a7r6qqI7HyUYSlezevlqt8f7w6dB+AsqWLy1WaES8RQIaGhWHJ7CnKx2Ie7Gs2QqtmfygrSn8nYFWFxqqA/MfavC9cgjicS91lZWUJzx3rlR/NXrgcV6/5RapX9UNxEJf7hi0QYXPES13A+uNK3BbtXeXKT7GHbHQrWKN7tmp86uoXK4DFSmBxiYDV0tISsyePVZqKbR3GTJguA9Ec2bMqAfuPViLIFHvF/hiw/viXAGJFrNgC4OC2dQgJDUXFWo3lqtyI8676/VGtuI0uYP1VrWIQDFi1+4chA1btehp6bwxYDX0GWT8FKEABClCAAhSgAAUo8DMBBqw6eD8G/vU3Ll31lV9bjnhKvXiUCAfDEY6VC2bIJxtywNq4QW25SlJ1KStYN6xQ9upU/UwEhRev+GD8tDly39KVC2dGKy/avHz5WtliIWJDsb1B49Ydlf1jI/5Mn1awThwzTK62/NnVzLkrGtWrHeUgpwuXr6LnwL8gDqYSK3izZM4IEVZXrddc7QpW1Yph1bPEClZxn9iXNLqANbpnq1awHti2Tvnqv7oxaBKwrt+8HTMXLNN4BevY4f+LtGJZrGC9c+++XBErrt9ZwcqAVQd/0P2iSwascW+uz09kwKrPs8PaKEABClCAAhSgAAUoQIHfFWDA+ruCau4Xh/2IkLBXVxe5z6nq8jrjLfcljbjyU18C1sPHTuKvsd+/aq2qeersRfJgKrFnrNhXVVyq0E7sObpywSzlECqxB+tp7ws4tufbHqx+1wPlSsXkyZMpBmIFb8Ct20po9iOf2Bu0XvP26N6pnbLHacQ24iv67h5bsG3dcqUe1c8XLl8N9/VbsHrxHGVv1j0HDkPs0xlxn9LfWcF66tx5DBz2N4YN7I0GdWrIR4stIN68fYdsWTNDHOxUs5ETqjiUx7gRQ5TS7z94BCsrCyV4vnH7Dtp16SO3DMiWJXMkBtVX6w/t8FBW8Ir7W3RwVRuwRtxeIuDGLbR37SfDWXEAmLqA9WfPPnv+Ivr9OQqD+riiacO6Sl1Xff1hUyCv8hcGmgSsqkOpIu3B+l996vZgFYdZiUOtxKXagzVnjuzKvrVd+w5G0Ju3cg9W1YFoYn/dvQePQGyTIN6z31nB2qZTL2TOnFFZpauDPxoSVJcMWBPUdP9ysAxYf0nEBhSgAAUoQAEKUIACFKCAAQswYNXB5IlDjXoOHAYRSolT1fPnzYUHDx7j6MnTyJIlExbPnKTsQ6oKWCtXLI8CefNEqcauZDEUti0Q6fPY7MH6qy0CrvkHoFOvQShnV1Keyq5afblm/RbMW7ICzRvVl3vEihPcVaGdWJ1byDY/7MuVga9/gDzlvbZjFYwaOkAGjY3bdIKZqRlqV6+C7Fkzy1Pnd+8/hDYtmihf8548az5OnDqHTasWI0mSxLh4xVfaiVWZaVKliuLRa9Bw5MqRLdLer6pG4jAmsf9pipQpULdGNXx4/xE79x9EBmtrrFoyG+ZmZrLp7wSsoaFhcO7aB0+ePUODOjXlatzdBzwRGhqKDSsWyUOzps5aiM0790CEiCWLFcGjR0+w5+BhOFZxUALE5as95L687kvnRBnjFR8/eaCTuN+xsgNCQkKwcesuBN66rTZgFXvairmxsrTEnv2eePHqFdYsnitDZnUB68+eLcbX3rUv7j98hFrVqyJntqzw9bsuv6o/YnA/1K1ZTdarScAq9r9t1r4bTE1MUL9ODXkwlahPHFRVpnSJKFsEiPepWmV75MmVU/6uiHdy2IBeaPDfYWKqvwQoXLAAKlUoh8Cbt3HwyHEZxKv2hv2dgFUE55d8fOHs1Ax1alZFemtrHfzpkHC6ZMCacOZak5EyYNVEiW0oQAEKUIACFKAABShAAUMVYMCqo5kTK/BWe2yWh0c9e/4SaVOnhH25sujo3DJScKg6bCi6Mnp0bo92Tk0j/VisghWH/2xcueiX1XtfuIw+g0dgyZwpkYJasU9swfz5ZBiqukQwuP/wUWTJnFkeGiQusTrzr7GTcMXXD00b1pOHRalCO7Ef5otXr3HW+yK+Bn+VJ9kP7NUNYq9RcT14+BirPDbJoOzBo8cysKrlWAXOrZspKyHFitZDx04qJ8/PWbQc/gE3MW/aP1HG9u7de9Rp1hazJ49DyWKF1Y7dP+CGDISvXQ+Uh4iVK10Cvbu5RNqyQByStXTlWhzfu0UGoqqrx8BhMoSNuK/oMa8z+HPUeBmE5s6ZQzZ9+fo15ixcjjPnL8LUxBRFCtmgT7eO8qv84hL7hbqtWS9D1TdBb+V99uVKw7lVc+V5Lj0GwKFcGXRydlI7ju2792PNhi1yq4ScObLJVc+jx09F987tIQ4XE5c45Grtxq2YOHoYlq9Zj9t37iFzpoxw7dROzoW4goODUaVec7miVfUe/erZr4KCMFeO7xJCQkNgky8PGtarheqVHZRaxX634mv3MyaMVj4TYefIf6ZGWpUr/pJh9sKluHHrLjJnzIAmf9SVK6LTpE4t94gVlyoUHf6/vhD7+PpdD5BhcZOGdeUq3IiXeMaqtZtw7+FDpE6ZUgahnZxbK+G5uvdd01rFiuuxk2bi7oOHsjax5yyv2AswYI29nTHeyYDVGGeVY6IABShAAQpQgAIUoAAFVAIMWPkuxFggun09Y9wRb/gtAVXAKg65MuRL3apTQx4Pa/8mwICVb0JEAQasfB8oQAEKUIACFKAABShAAWMWYMBqzLOro7ExYNURbAy7ZcAaQzA2j1MBBqxxyq33D2PAqvdTxAIpQAEKUIACFKAABShAgd8QYMD6G3gJ9VYGrPox8wxY9WMeWIV6AQasfDMiCjBg5ftAAQpQgAIUoAAFKEABChizAANWY55dHY1Nta9n907OaNuyiY6ewm5/JbB4hbvcg/Xo7k2/aqrXPz9/8Qp6/284ls6dgkI2kQ900+vCWdxPBRiw8gVhwMp3gAIUoAAFKEABClCAAhRIKAIMWBPKTHOcFKAABeJQgAFrHGIbwKO4gtUAJoklUoACFKAABShAAQpQgAKxFmDAGms63kgBClCAAtEJMGDluxFRgAEr3wcKUIACFKAABShAAQpQwJgFGLAa8+xybBSgAAXiSUAfA9a6LTuiaYPa6NS2RSSVSbMX4aqvP9YsmoHJsxfDxz8Aq+ZP/W25Dx8/ws6xETavXADb/Hl+uz/RwdVr15ElUwakSZ1KK/3FVScMWONKms+hAAUoQAEKUIACFKAABeJDgAFrfKjzmRSgAAWMXEAfA1YRpF664ot1S2dH0q/VrL0MXru2b4XLvv54/ToIVRzK/fYMvXv/AWVrNMZGt3koZJPvt/sTHVRv0g69OrdDo7o1tdJfXHXCgDWupPkcClCAAhSgAAUoQAEKUCA+BBiwxoc6n0kBClDAyAX0MWAVB6o59xiE47s8YJ02jZyBW3fuo36rTtixdgny5sqh1VnRScDauC16dnZG43oMWLU6WeyMAhSgAAUoQAEKUIACFKDAbwgwYP0NPN5KAQpQQN8EgoND8OLVa6ROlRIWSRLHW3n6GLCGhoahYr0W6N+9I5r/UVfaLHffiA3bdmPfxhXyn2ctcoOPXwCWzJwg/9k/8Cb+GjcVd+8/RJGCNvKr+V++fMHcyWPkz18HvcGoSTNx6twFWFlYoGnD2ujdpT1MTU2hLmBduno9Nu/ch8dPnyFVyhRo1rAOenV2ln2d9r6Anv8bhV5dnLFmwzaEhISgfaumypYG3QeNwDGvs7JtmZLFsGLeFPnfN+3YiyWrPPD8xSsUts2Pvwb2RIG8ueNt7tU9mCtY9Wo6WAwFKEABClCAAhSgAAUooGUBBqxaBmV3FKAABeJTYMX6nXjy/IUswcIiCVKnTIHUKZIhdaoUMtCT/5wqOZJaWuq0TH0MWMWAh42bilevg7Bw2jg5frGitbBNfgzu01X+8/T5y+DrH4BlsyfJf27YugsSJTLHgB6dZfAqAtjK9mWxYOpY+fOu/YfhydPnGNSrC56/fIWxU+egn6sLOrRqpjZgFWGo2EM1bZrUuHjlmmy/dslMFC1og5Nnzsv+qlUsL0PVU94XMG/pangsmy1/HhIaippNnOHq0hpNGtSGuZkZvM7+i+4Dh2PU4D6wyZ8Xazdtx4kz57F/0wpYWljodI5j0vnPAlb/m3dw/MwFvHr9JiZdsm0EAfEuiN93S4skSJEsKfLlzoH8eXLAyiIJnShAAQpQgAIUoAAFKECBOBBgwKojZLFyaYX7ehw+cQqvXr1GhnTpULt6FbRr1QyJzM21/lTXfkNgaWmJGRNGR9v3nEXL4bF5B47v3QIzM1Ot18AOKUCB+BfYeeAYfANu/bKQTOmt0b5Fg1+2i20DfQ1YDx3zwqCR43Fq32a5QtS+TjO4zZ2C0sWLyDPrcvwAACAASURBVKFGDFjfvnuPcjWbyLC1vF0J+fM23fojRfJkMmD98uUrSlSpj6WzJqBCmVLy5xNnLYSvXwBWL5yuNmD90bN647bo370T6tWsqgSsx3evh3Wa1BArbsvXaoKendrJlazi+nEP1vHT5+Pl6yBMGztM/lzcU6paA6ycNxXFCtvGdvq0ft/PAtbF7lsYrmpd/FuHObNlRqVyJZE5QzodPYHdUoACFKAABShAAQpQgAJCgAGrDt6D4OBguPYfimv+AahYvgxyZM8K/4AbEPv/VShbGlPHjYCJiYlWn9yl9yAZsM6e/G1Vlbprz4HDOHH6HP4ZMVh+fZUXBShgfALvP3zEwtXfwkPVFY5wmIT/92fOf/9hnSYVOrdurDMAfQ1YP33+jAq1m2HK6KH4GvwV46bNw4ndG5S/dIoYsAbcvI1Gbbvh6I51SJ8urbQS2wW8CnojA9bbd++jnlMnHNyyClkyZZQ/99iyC0tXe+DQ1jVqA9bVG7Zi5brNePz0OcLDw+U9k0YPQYNajjJgdR04HD5e+5R5ad21H+zLlpIhq7h+DFh7DxkNz+OnoszjrAkjUaOKg87mN6Yd/yxgXbJ2C16+4urVmJrGpH2uHFngaF8G4veeFwUoQAEKUIACFKAABSigfQEGrNo3xbZd+zBp5nwM6uOKpg2/7fMnrulzF2PT9t1YNHMSihSy0eqTNQlYtfpAdkYBCuitgJf3ZZw4ewHf4jsg0l/niA9NAEcHO9gVL6yzMehrwCoG3PN/I5EiRXKEhobC3Nwc44cP+v7ndIQtAtQFrMP/mSZXjIqAVXVA1qGtq5E5YwbZhwxY16zHoS2rowSsfgE30bJjLxmo2pctjaRWVqjTogN6d22vBKzdBw3H1ZPfA9a23fqjfJmS0QasYsuDsLAw/PPX9zGIOvTtWwq/2iLgmNd5vH77TmfvIzsGzMzN0Lh2VeTNmY0cFKAABShAAQpQgAIUoICWBRiwahlUdNfvz1G4dj0Q+zavibRSNDgkBE+ePEO2rJm1/lQGrFonZYcUMFiBC77+OHD0DBAu1q5+D1i/Ba7hMDM1Q59OrXR6CJY+B6zikKmpc5dIjbHDBqB6ZXu1AatqiwC3uZNRtlRx2UYEnsn/2yLg85cvKFmlAZbNnojydiXlzyfPXoyr1/wjbRGwYflcefjU7gNHMGXuYrkiVnWJ1bRD+3ePUcDao2NbNKlfS3YxZ8kq7D10FDvXLlVCVbHHrDiMS58uHnKl29kQ35x59+Gj/P/bdx/C78ZtvHn7Xu1DHR3KwK54Id0WxN4pQAEKUIACFKAABSiQwAQYsOpgwps5d0Vi80RYu3zeL3u/HngD85euhq/fdSRKlEju89ezawekTZNGuff16yDMXboSp8/+iy9fv6BggXzo3skZBW3yK21+DFhv3r4L1/5/wrGyA/7s31O2W+y2Bu4bt+LYns3Kfa+CgjB3kRtOn7sA8S9oYmWteH7eXDmVNvWbt0emjOmwZM7UX46HDShAgfgTePr8FfYd8cLjZy9EjiqTVfkf4qvoYluS/z6zyZsTjWpX1Wmh+hywigCyYr2W8vCq0/s3RzoM6sdDruq36gQrS0sM7t0VV/0CMGXO4kiHXHXuOxTPX77E4N7d8OLlK4yePAt9unaAS+tmEH+pVrxSPXnoVZvmjSD+XG7ZqTdGD+kr92zduvsAFixfE2mLgF+tYG3aoQeyZc4kD+USq2b9A2+iafseaNawDv6oWwPeF65g8cp12LdxBdJZf//fEZ1OtgadM2DVAEnLTW7dfQjPE2fxMijq9guOFcvArhhDVi2TszsKUIACFKAABShAgQQswIBVB5Pf0MlFnhK9YMbEn/b++OkztO3SW574W6t6Vbx/9wF7Dx1GxvTpsXLxLHlCtPjqp0uPAbh3/yHq1KyKlCmSY5/nMbwJeouVi2YiW5Zvq2EjBqxv376DS88BSJc2DeZMGSeDW3HNX7oSazduxcn92+Q/i8NQXLr3lydfN65fC1ZWVti1/5A8YXvdsrlKyNu6Y09kyJDupwdo6YCRXVKAAhoKfPryFUe9zuHKtUBlWwBxq9x7FSbKKlbVataWf9RCrmzaX0kfsVx9DlhFnc49Bsk/e+dOHhNJedYiN/j4BWDJzAnyc/FthOnzl+OKr5/8y620qVPh4+fPcosAcYk/L0dPmoVT5/6FhYUFmjaojb7dOijfXpg4cwE8tu6SX+EXB1nNXboK7hu3yz/fa1atCO9LV+HaoRXq1qiK094X4DpwBC4f363UJOqsYFcCri5t5Gd7PY9h3NS5yJMzO1YtmCY/Eytj5yxZiecvXiF/3lwy3BV969PFgDX+ZuOU9yUcP3sxSgEtG9ZEruxZ4q8wPpkCFKAABShAAQpQgAJGJMCAVQeTWadpOxS0yYdp/4z8ae+L3FZjjccWrFw0C7lzZv/2L8r7PTFuyixMGTscDuXLwPvCJfQZPFKuQv2j3revhN699wDtuvZBs0b10ce1o/xMFbDOmDAG/YeOwv0HD7Fs/nSkSfX9a6I/BqxnvC+g/9DR8tAt+3J2sp/HT57CqWMPdGzrhPatm+tAh11SgALaEggLD8fFq/44fkasbg+O0u23cPW/nVj/W8WazMoKPTu2jLwvq7YKitCPvgessR3ygOHj5F90jRrcN7ZdJMj7GLDG77Tff/QEW/YcxqfPX5RCEidKhA4tGyBNqpTxWxyfTgEKUIACFKAABShAASMQYMCqg0ls0LIDsmbO+MsVrMP+noQbN29jw8qFShViO4C6zZ1lcNqqWSN5KNa0OYuww8MN6ay/nWItLrGqNEuWTDKIFZcqYM2dKwfWb96BYQN6oUHdmpFG92PAunHbLnnw1vzpE2BpkURpO/TviShTsjiGDuilAx12SQEKaEPgweOn2OPpJU+0V3dly5wBdarZ4+xFH1z2DVCaOJQpAYcy3/YT1eVlLAGrOEQqQ7q0qFaxAm7cvovRE2dizqTRqFShjC75jK5vBqzxP6WPnz7Hms17EBoWphSTJWM6tGtWP/6LYwUUoAAFKEABClCAAhQwcAEGrDqYQE33YHXtN0T+i86S2VOUKsLDw2FfsxFaNfsDvbt1lPumurlvwPG9m5Wv+ovGPQYOw6dPn+E2f7q8VwSst+8+wIePH+Wq1eQpkmH14tlIZG6u9P1jwCpW0K5w36hWQKyeVYW3OiBilxSgQCwFPnz4hEMnzspDbNRdKZInhaNDWRTIk0P++OPHT5i93ENp2sulJZIltYrl0zW/zVgC1tPeFzFroRsCb91Beuu0cHZqjFZNG2oOwZZSgAGrfrwI/jduY9u+o5GKadWoNnJkzaQfBbIKClCAAhSgAAUoQAEKGKgAA1YdTFy/P0fBL+AG9m5arezDJx4TEhqKp0+fI0vmjPKp2l7BKvYN7NjOCcUK26LvkFEyoG3dvJEywuhWsB7Ytg7JkyXVgQS7pAAFtCUg/vzwvugDr/NXEBISEqVbsadn2ZJFUKFUUZiZm0X6uVjFesTLG7lzZEWLBjW0VdJP+zGWgDVOsBLAQxiw6s8kb97ticDb95SCCuTNicY6PvROf0bPSihAAQpQgAIUoAAFKKAbAQasOnDdsmMvpsxeEGnfVPGYmQuWYuPWXVg4YyKKFLLBwuWr4b5+C1YvnoOcObLKSvYcOIyxk2di8tjhqFi+DM79e1GGpRG/8n//wSO06dIbTf+oi76uneR9YgXrl68hWLlwBkxMTPDn6Aly/9YNKxYoh1X9GLCePX8RIgwe1McVTRvWVSSu+vrDpkDeSKtfdcDELilAAQ0Fbty5j0PHzyLo7Tu1d+TPlR01KpeL9i9KxF6t/oG3kTVzeqRIlkzDp/5eMwasv+dnbHczYNWfGX36/CXc1u9QChJ/OdO3S2v+b77+TBEroQAFKEABClCAAhQwQAEGrDqYtK9fg9Gt3xBcD7yJyg7lkTN7FlwPvIXT5/5FmVIlMHPiaBmCigOl2nbpjRQpU6BujWr48P4jdu4/iAzW1li1ZLY8ZTo0NAwu3fvjwaPHqF+7OlKkSI69Bw/j1asgrFo0C9myfjsJXLUH6+zJ3062fvT4KVp16gHHyg4YOaS//OzHgFX03d61L+4/fIRa1asiZ7as8PW7jsPHvTBicD/UrVlN3teuSx+kT2/9y0O7dEDJLimQoAWC3rzD3iNeuPvgsVqH1ClTyH1Ws2f5tipeny4GrPo0G/FfCwPW+J+DiBWs3LATj5+9UD5qUqca8v+3rYh+VcpqKEABClCAAhSgAAUoYBgCDFh1NE/v3r3HsjUeOH7yNF6+DpIHVNWuXgXtWzWPtJeqf8ANzFuyAteuB8rPy5Uugd7dXJRVp6K8V0FBmLvIDafO/Yvgr19hkz8fenRxRiGbAkr1Yj9XS0tLzJgwWvls2SoPLF21FsvnTYNtgXxyP1f3jVtxbM9mpY3se+FynDl/CSGhIbDJlwcN69VC9coOSpt6zZyRKWMGLJ37fa9YHbGxWwpQAEBwSAi8zl6C92XfSAfSqHDE6d8OZUugdFHbSNuQ6BMeA1Z9mo34r4UBa/zPQcQKTp67hJPnLiofFcqfGw1qVtavIlkNBShAAQpQgAIUoAAFDEiAAasBTRZLpQAFjF/g2vWb8DzlDXGYlbqrsE1eVLW3Q1JLC73GYMCq19MT58UxYI1z8p8+UGw7smnXIaWNdepU6NymsX4VyWooQAEKUIACFKAABShgQAIMWA1oslgqBShgvALPX77GnsMn8fjp96/tRhxt+rSpUdfRARnTWxsEAgNWg5imOCuSAWucUWv0oGcvX2H5uu1K22RJrdDLpaVG97IRBShAAQpQgAIUoAAFKBBVgAEr3woKUIAC8Sjw5WswjpzyxmWf6whXU4eVRRJUrmCHogXzwSQe64zpoxmwxlTMuNszYNWv+f385QtmLlmrFJXI3BwDXdvpV5GshgIUoAAFKEABClCAAgYkwIDVgCaLpVKAAsYjEB4ejku+ATh2+jw+f/kaZWDiILwSRWxQuVwpJEmcyOAGzoDV4KZMpwUzYNUpb6w6nzjXLdJ9f/ZyiVU/vIkCFKAABShAAQpQgAIUABiw8i2gAAUoEMcCj548l9sBvHgVpPbJWTKmR11He6RNnSqOK9Pe4xiwas/SGHpiwKp/s8iAVf/mhBVRgAIUoAAFKEABChiuAANWw507Vk4BChiYwIdPn+F54iyuBdxSW3myZFZwtC8D23y5DGxkUctlwGrwU6jVATBg1SqnVjpjwKoVRnZCAQpQgAIUoAAFKEABKcCAlS8CBShAAR0LhIaFwfuyL7zOXkJwSEiUp5mZmaJM8cKwL10M5onMdVxN3HTPgDVunA3lKQxY9W+mGLDq35ywIgpQgAIUoAAFKEABwxVgwGq4c8fKKUABAxC4c/8R9h7xwpu379VWmydnVtSqXB4pkiczgNFoXiIDVs2tEkJLBqz6N8sMWPVvTlgRBShAAQpQgAIUoIDhCjBgNdy5Y+UUoIAeC7x99x77j53GzTsP1FaZMkUy1Klqj5zZMuvxKGJfGgPW2NsZ450MWPVvVhmw6t+csCIKUIACFKAABShAAcMVYMBquHPHyilAAT0UCAkOgdf5yzh3yQehoWFRKkxkbg77ssVhV6wQzExN9XAE2imJAat2HI2lFwas+jeTDFj1b05YEQUoQAEKUIACFKCA4QowYDXcuWPlFKCAngn4Bd6Gp9c5vH//UW1lBfPnhmPFskhqaaFnlWu/HAas2jc15B4ZsOrf7DFg1b85YUUUoAAFKEABClCAAoYrwIBVR3P3+OkzLHFbg4s+1/D2zVtkzZIZRWxt0LpFY2TOlEFHT/15tw61GqFh3ZoY3LeHbOjmvgGL3dZEuilVypQoZJsfndo5wbZAvhjXeeDwcSxcvhpPnj7D4tmTUdi2QKQ+tu/ej4kz5mHFgukokC9vjPsXN5w6ex7LVnvgzt17SJfOGvVrVUerZo0gDgpSXWFhYVjhvgE79x/C69dByJEtK1zatECVihUiPTMkNBRrPLZgn+cRPH/+AtmzZUWHVs1RuWL5WNXGmxKmwMvXQdjj6YWHT56pBbBOkwp1qzkgc8Z0CQaIAWuCmWqNBsqAVSOmOG3EgDVOufkwClCAAhSgAAUoQAEjF2DAqoMJDgp6gzade+PDp49wrFJRHl5z5+59eF+4hNSpUmH7uuUwjYevBpev3hAN6tbEsAG95KiXrlqHZavWoWWThkiWLCnCQkNx/+FjnDh9FqYmplg4YwLy58ujsdD7Dx/RsGUHZM2cCbWqV0G9mtWQKlVK5f5Pnz+jubMrihexxbgRQzTuN2LDfy9dQa9Bw1G8SEE4lC8LH7/rOHriFLq6tJUBquqat2QF1qzfIgPV/Hlz47jXGVwPvImZE0ejTKkSSrvJs+Zj6859qF6lIgrky4NjJ0/Bxy8A/4wYjGqVHWJVI29KOAJfvgbj2Jl/cfGqP8LDw6MM3CJJYlQuXxrFC+WHiYlJwoEBwIA1QU33LwfLgPWXRHHegAFrnJPzgRSgAAUoQAEKUIACRizAgFUHk6sKLhfOnIRihW2VJzx89ATPX76S4WB8XNEFrNs9liO9tbVSks81f3TtOwQO5ewweexwjUsNCLyJ9t37Y/TQgajlWDnKfWLF7PJV67B2+TxkyxK7g30GjxiHSz7XsG3tclj99zXr/kNH43rgLezZtEo+Mzg4GDUatULZ0iUxacww+dmHjx/h5NIDeXLlwMyJY+RnT569QOPWHdG8UX0M6NVVfiZWtLbv2hdhCMO6ZfM1HjsbJiwBEaVeuRaIY6e88fHzlyiDF1FqscIFULWCHZIkTpSwcP4bLQPWBDnt0Q6aAav+vQ8MWPVvTlgRBShAAQpQgAIUoIDhCjBg1cHcDft7Es56/wvPnRt00Hvsu9Q0YBVP6DN4JHz9r+PQdg+NV96pVpfOmjQm0ipR0d+bN2/RzLkrajlWxaA+3WI9CBH+fvj4CWVLf1+FushtNVa4b8TR3ZuQJEli3Ln7AK069UD3Ts5wbtVMeZZY+frg4SNsW7dcfuZ1xhuDho/FopmTUDRCEC62TVixdiOO7Noo++NFgYgCIpjf43kSz16+VguTKYO13A4gXdrUCRqOAWuCnv4og2fAqn/vAwNW/ZsTVkQBClCAAhSgAAUoYLgCDFh1MHdTZy/C5h278eMKVnWPEqeMu7l7YM9+T7wKeoMc2bOhY5sWqOzwfQ/Ql69eYdaC5fC+cBmfP39G9mxZULt6FTRpUFcJADVpE5OAdeb8pVi/ZQcObvdAsqRW8mv04uv0MyaMRjm7klGGcuGyD3oO/LZaVHUtmTNF2YN15oKl2LnnADauXow0qVKpVT9y3Asbtu7E7XsPEPz1KzJnzIi2Tk3VroaN2MHAv/7G7bv3sWXNEvnx9cAb6NB9AAb17oamf9RTmg4ZNR6Xrvpi/xZ3+Zl4ngjDowSsK9zhtma9DMhVq2R18JqwSwMT+PDpM454ecPH/4baypMmtYRjBTsULKD5thoGRhCjchmwxojL6BszYNW/KWbAqn9zwoooQAEKUIACFKAABQxXgAGrDuZOfFW+Y6+Bch/TqpUqoGjhgihkk1/uBfrj3qvT5ogwdg8a1a+F3DlzyL1Cz1+8gmn/jET5MqVkdf3+HAX/wJto26IJ0qZJDV+/AJw5/y/mTfsHGdJ9OzRHkzYxCVhVq0J3b1olA9HdBzwxZ5Gb3Ju0VPGiUdQ+fvqMnfsOYOa8pejr2hG2NgVQIF9uWCRJAnHgV8sO3WFlZQlzM3OYm5nKvVG7dWwLS4vvp6mPGDsZiZMkRmFbG9n/noOeuOYfiDVL5iBXjmxqZ+qqr9jOYDA6tnNCl/atZRvVZyOH9EedGlWV+/6eOB1HT57B4V3fVhbfvfcATh17oGXThujXvbP8TATeHVz74e27d9ju4aaDt4NdGpqAODDt/BU/nDx7EV+Dg6OUb2ZqCrtihWBftjgSmZsb2vB0Vi8DVp3RGmTHDFj1b9oYsOrfnLAiClCAAhSgAAUoQAHDFWDAqqO5u3D5KmYtWIaAG7eUJ4gDrvr16Iya1SrJzz5+/IRajVujRZMG6N2to/wsOCQELt37I22aNBBftReXY4MWqF61Eob+dziVupI1aROTgHXZKg8sXbUWW9cuR8b03/dn/RmXahXr7MljYVeymNJ09sLlWLdpG4oUskGlCuXkYVOHjp6AY2X7nx52JYLZJm06Y/jgvqhX0zHKo8WhWu1d+0KcLeS+dI4S1l687IMeA4dh/MghqFrJXrlPrMDdtfcQju/bonz255gJOHbitAxi8+fJhaMnT+Oyjx9aNWuEPq7f5oRXwhW49/AJ9h72wus3b9Ui5MiaCXWq2iNVyuQJFymakTNg5SsRUYABq/69DwxY9W9OWBEFKEABClCAAhSggOEKMGDV8dy9CgqC//UbuHrND1t27sO7d++xeNYkFC5og5u376Jtl97o170TihUppFSyct0m3Lx1BxtWLpSfdes3BDdu3oZjlYqwzZ8PObJnlV+9Txzh8BxN2sQkYP1xBasmTNEFrA1adkDqlCnhtmAGzMxMZVdi5e6m7bvlGCMeePX5yxc8ffocnz5/hjih3bXfEPTt0RlOTRpGKeGvvyfhxKmzWDhzIgra5Fd+rqxg/XMA6lSvonz+96QZOHritLKCVfxAhNwLlq3CMa8zCAsNQ3BoCD59/IT1KxYgU8YMmgybbYxQ4N37Dzh47AwCbt9TO7pUKZKjeqWyyJtT/cpqIySJ8ZAYsMaYzKhvYMCqf9PLgFX/5oQVUYACFKAABShAAQoYrgAD1jicuxu376Bdlz5o3byRXLHqfeGSPExK3SW+Tu+5Y7380eOnzzFn0XKIQ6Tevn0nPxPhn9giIFOG9Bq3iUnAKvZMXb/5+x6smjCpC1jFKtMafzihs3NrdHJ2Urq5dPUauvf/ExNHDUXlit/2m12yci3cN2zBly9fIz1OXcAqtlWYOnsh+vfqghaNGkRq7x9wAy49fr0H649jevn6NZq364aG9WoqWwZoMm62MR6B0JBQnPr3Cs5euIqQ0NAoAzM3N4d96aKwK1EY5mZmxjNwHYyEAasOUA24Swas+jd5DFj1b05YEQUoQAEKUIACFKCA4QowYI3DuRP7e1ap2xR1albDsIG9lRWsE8cMQ2X7chpVIgJWsdpy/LQ5kfYOjXhzdG1iErD2HTIKPtf8cGjHepiYmGhUm7qAVawQdWzYUu6PKvZJVV2qgFXsNVuhbGmILRV6DvwLrh3boXqVisiSOSPEataq9ZpHWcEqtl3o0ud/qFDWDhNG/Rmltjt3H6BVpx7o0bk92jk1VX7e+3/Dce/+w2j3Vp06ayH2Hz6KTasWI2XKFBqNmY2MR+D6zbvwPHkWb999UDso27y5UL1iWYjDrHj9WoAB66+NElILBqz6N9sMWPVvTlgRBShAAQpQgAIUoIDhCjBg1cHcif1LLS0t5N6qEVe5HTh8HKPGT8WAXl3RvFF9iIOhajZyQhWH8pH2Ir3/4BGsrCzkPqziEitXixcprHy9XnxWv3l7VLQviyH9emjcRtOA9Zp/ALr0GYxydiXlYVuaXtFtEdDMuSusLK3gNn+6MoYZc5dgw7adyh6vYrsAsW3AoR0eSGplJR8pHFp0cI0UsIrAtkOP/hAHD7nNn4HkyZJGKS84OBjV/3BC+bKl5QpZcYn7xIFWuXJkV/a2jXjj/YeP0LpjT3Tp0AbOrZppOmS2MwKBV0Fv5D6r9x89VTuaNKlSoq6jPbJm4pYRMZluBqwx0TL+tgxY9W+OGbDq35ywIgpQgAIUoAAFKEABwxVgwKrluROrLrv1HSIPt0pnnRZFC9kgS+ZMuHP3Pk6cPoec2bLKvUiTJEksnyxWTW7euQf25exQslgRPHr0BHsOHoZjFQf8NagPfK75y7Azb66c8qv0qVKmwOmz/+LUufOYMWG0DEE1aSOeFV3AKg50Sp48GUJDQ/Ho8RMcOX4K4QjHgukTYFsgn6xz78EjmLd4Bf4ePkjWqe6KLmDd53kUYyZMR/EiBVHJvhwCb9zC3kNH0ah+bSUgvuLjJ/eaFQ6OlR0QEhKCjVt3IfDW7UgB6z9TZ2PXvkNo2qAuCuTL/b0MExPUrlFVOcVdbKmwduM2VK/sgAL588q9V339r2P6+FEoX6ZUlPKHj52EK77+ck9YiyRJtPxWsDt9FPgaHIwTZy7g3yt+CBMnpf1wJUmcCJXKlUKJIjYw1XAVtz6OM75qYsAaX/L6+VwGrPo3LwxY9W9OWBEFKEABClCAAhSggOEKMGDVwdyJ1ZUiBPQ6443AW3fw5s0bZM6YEeXLlkI7p2aRVl2KfR7d1qyXoeqboLfInTMH7MuVhnOr5spqz/MXr2DTjt0ICLwl+8qaNQvatmiMGlUrKdVr0sahViM0rFsTg/t+W/Xq5r4Bi93WRBIQX40vVCA/Ojq3RCGbAsrPtuzYiymzF0QbUIqGl3385KFU86aNR8lihSP1e+jYSaxet0muSrW2ToM61auirVNTJRAVjbfv3o81G7bg5cvXyJkjG1zatsTo8VPRvXN7NPujnuzPuWtfGbqqu/ZvcUeKFN9OcxfbMSxf44Hd+w7h9Zs38iAtlzYtZXD94xUQeBPtu/eXgXb92tV18EawS30SEFGqj38gjnqdx4dPn6OUJjbEKFowH6rYl4Hlf38Rok/1G0otDFgNZabipk4GrHHjHJOnMGCNiRbbUoACFKAABShAAQpQ4OcCDFj5hlCAAglG4OmLV9jjeRJPn79UO+YM6dKirqMDMlh/256DV+wFGLDG3s4Y72TAqn+zyoBV/+aEFVGAAhSgAAUoQAEKGK4AA1bDnTtWTgEKaCjw8fMXHPXyxhW/QLV3JLWyQNUKdihkkxeaHemm4YMTcDMGrAl48tUMnQGr/r0PDFj176rbAwAAIABJREFUb05YEQUoQAEKUIACFKCA4QowYDXcuWPlFKDALwTE3qoXr/jj+Nl/8eVrcJTWpqamKFXUFpXKlYy0XQVhf1+AAevvGxpTDwxY9W82GbDq35ywIgpQgAIUoAAFKEABwxVgwGq4c8fKKUCBnwg8ePwUezy98CrojdpW2TJnQJ1q9kiTKiUddSBw7eZ9hIaFo6RNTlhZfDvUj1fCFPj4+Ssu+N+BmakJCubJljAR9HDUDFj1cFJYEgUoQAEKUIACFKCAwQowYDXYqWPhFKCAOoF37z/A88Q5+N+8oxYoZYpkcHQoi/y5sxNQhwI37z+BCNasUyVDjkzWPDBMh9b63PWnL19x9/ELvAh6D0uLxMibLaM+l5ugamPAmqCmm4OlAAUoQAEKUIACFNCxAANWHQOzewpQIG4EQkJDce6iD06dv4KQkJAoDzUzN0OFUkVRtmQRmJuZxU1RCfgp7z5+xp2HzxKwAIf+o0DOLOmR3MqCMHoiwIBVTyaCZVCAAhSgAAUoQAEKGIUAA1ajmEYOggIJW+DG7fs4dPwsgt69UwtRIHcOVK9UFsmTJU3YUHE8ehGyPn0ZhC9fgiH2w+WV8ARMTUxgkSQR0qdNxXBVz6afAaueTQjLoQAFKEABClCAAhQwaAEGrAY9fSyeAglbQOyvuv/oadx98FgtROqUKeQ+q9mz8GvJCftN4egpQIEfBRiw8p2gAAUoQAEKUIACFKCA9gQYsGrPkj1RgAJxJBAcEoKTZy/C+/I1hIWFRXlq4kSJULFsCZQqagtTU9M4qoqPoQAFKGA4AgxYDWeuWCkFKEABClCAAhSggP4LMGDV/zlihRSgQAQB3+s3cdjLGx8+flLrUsQ2L6ral4GVRRK6UYACFKBANAIMWPlqUIACFKAABShAAQpQQHsCDFi1Z8meKEABHQo8f/kaew6fxOOnL9Q+JX3a1Kjr6ICM6a11WAW7pgAFKGAcAgxYjWMeOQoKUIACFKAABShAAf0QYMCqH/PAKihAgWgEPn35imOnvHHZNwDqjkkSK1Ur25dGUdv8MKEiBShAAQpoJMCAVSMmNqIABShAAQpQgAIUoIBGAgxYNWJiIwpQIK4FwsPDccnnOo6d+Refv3yN8nhxOnmJIjaoXL4UxJ6rvBKOgN+N2zhx9qIcsNhr1zZvroQzeI6UAloSYMCqJUh2QwEKUIACFKAABShAAQAMWPkaUIACeifw6MlzuR3Ai1dBamvLkjE96jraI23qVHpXOwvSvcBi9y149fqNfFCa1CnRtU0T3T+UT6CAkQkwYDWyCeVwKEABClCAAhSgAAXiVYABa7zy8+EUoEBEgQ8fPuHQybPwC7ytFiZ5sqRwdCgDm7w5CZeABRgMJeDJ59C1JsDfI61RsiMKUIACFKAABShAAQpwBSvfAQpQIP4FQsPC4H3JB17nLiM4JCRKQeZmZrArURgOpYvBzNws/gtmBfEqwGAoXvn5cCMR4O+RkUwkh0EBClCAAhSgAAUooBcCXMGqF9PAIiiQcAXu3H+EvUe88Obte7UIeXNlQ81K5ZAiebKEi8SRRxJgMMQXggK/L8Dfo983ZA8UoAAFKEABClCAAhRQCTBg5btAAQrEi0DQ23c4eOwMbt59oPb5qVOmQK0q5ZEzW+Z4qY8P1V8BBkPanZuw8HBs3XsEISEhaN6gBsQBcryMX4C/R8Y/xxwhBShAAQpQgAIUoEDcCTBgjTtrPokCFAAQEhyCk96X4X3ZB6GhYVFMEiVKBAe74rArXhCmpqY0o0AUAQZD2n0pDhw7gwtX/WSnpYrYokblctp9AHvTSwH+HunltLAoClCAAhSgAAUoQAEDFWDAaqATx7IpYIgC4vAqT69zeP/+o9ryCxbIIw+xSmppYYjDY81xJMBgSHvQvgG3sPPAsUgdNqhZGYXy59beQ9iTXgrw90gvp4VFUYACFKAABShAAQoYqAADVgOdOJZNAUMSeP7yNfYdOYWHT56pLTt92tSoXdUemTOmM6RhsdZ4EmAwpB34Zy9fYeWGnQgNCQUibAtgZmaK9i0aIH3aNNp5EHvRSwH+HunltLAoClCAAhSgAAUoQAEDFWDAaqATx7IpYAgCX74G4+jp87jkcx3h4eFRSrZMkhiVKpRG8UIFwF0fDWFG9aNGBkO/Pw+fPn+B2/rtePvuAyB+N3/YdzVF8qTo6NQIFkkS//7D2INeCvD3SC+nhUVRgAIUoAAFKEABChioAANWA504lk0BfRYQUepl3wAcO30eIsj58TIxMUHxQvlRpYIdkiROpM9DYW16KMBg6PcmRfxlx9pte3H/4VMZroabmCh/wSF+d1V/2ZEza2a0/KMmxO8rL+MT4O+R8c0pR0QBClCAAhSgAAUoEH8CDFjjz55PpoBRCjx68hz7jnjh2cvXaseXKYM16lZzQLq0qY1y/ByU7gUYDP2e8WEvb5y76AOEA+Em4fger/7Xr1xtbiL/r3ypoqhcvtTvPZB366UAf4/0clpYFAUoQAEKUIACFKCAgQowYDXQiWPZFNA3gQ+fPuOw1zn4+t9UW1qypFZwtLeDLQ/P0bepM7h6GAzFfspu3LmPTbsOxagDpz9qIWe2zDG6h431X4C/R/o/R6yQAhSgAAUoQAEKUMBwBBiwGs5csVIK6KVAWFgYvC9fw8lzlxAcHBylRjNTU9gVLwQHu+IwT2Sul2NgUYYlwGAo9vN1/cYdbN13JEYd1KxUDiWL2sboHjbWf4Gl7lvx4nWQLNQ6dSp0btNY/4tmhRSgAAUoQAEKUIACFNBTAQasejoxLIsChiBw7+ET7D3shddv3qotN0fWTKhT1R6pUiY3hOGwRgMRYMCq3Ymip3Y9DaU3/5t3cOL0BYSbAJXKlYRNnpyGUjrrpAAFKEABClCAAhSggN4JMGDVuylhQRTQf4G3797j4PGzCLx9T22xqVMkR/XK5ZAnR1b9HwwrNDgBBoLanTJ6ateTvVGAAhSgAAUoQAEKUIACCU+AAWvCm3OOmAKxFggNCYXX+cvygJyQ0NAo/Zibm8PBrhjsShSG2BqAFwV0IcBAULuq9NSuJ3ujAAUoQAEKUIACFKAABRKeAAPWhDfnHDEFYiUgvk7qefIc3r37oPZ+23y5UN2hLJImtYxV/7yJApoKMBDUVEqzdvTUzImtKEABClCAAhSgAAUoQAEKRCfAgJXvBgUo8FOBl6+DsO/IKdx/9FRtO+s0qVC7agVkzZSBkhSIEwEGgtplpqd2PdkbBShAAQpQgAIUoAAFKJDwBBiwJrw554gpoJHA1+BgHD9zAReu+CEsPDzKPRaJE6NS+VIoUbgATExMNOqTjSigDQEGgtpQ/N4HPbXryd4oQAEKUIACFKAABShAgYQnwIA14c05R0yBnwqIKPWqXyCOnjqPj58+R2krotRiBfOjsr0dLJMkpiYF4lyAgaB2yY3Z88PHj1izfjMOHT2JZ89fIG3qVLAvVwYd2rZA2tSp1ULevH0X7br2QZ0aVTFicD+tYgcHB6NKvebo3skZbVs20ajvl69eoX6LDj9tW6JYYcyfNv6X/XlfuIw+g0dgyZwpKGxb4Jft9b3BYrc1cN+4Fcf2bNb3UlkfBShAAQpQgAIUoICRCzBgNfIJ5vAoEBOBJ89eYO+RU3j6/KXa2zJlsEbtqvbIYJ0mJt2yLQW0KmDMgaBWoTTszFg9RZjZY+Aw+Fy7jnJ2JZE3d048ePQEx73OIEvmjFg6ewpSpEgeRWmR22qscN8IKytL7N20BokTJ9JQMnKzzTv2wPeaP0b+OUD5wdevwahctym6urSFS5sWGvX76fNnuG/YqrS9dMUX/166ghaNGiB5imTy8yyZMspA+FfXGe8L6D90NBbOnIRihW1/1TxOfn7Zxw8r3Ndj+P/6IG2amP1vy/ylK7F241ac3L8tTmrlQyhAAQpQgAIUoAAFKBCdAANWvhsUoAA+fv6Coye9ccU/UK1GUisLVKtQBoVs8lCLAvEuYKyBYHzBGqvntl37MGnmfPTq6oI2LRorvIePncRfYyfDuVUzuZL0x6tFe1e8ff8eb968xaS//0KlCmVjNTWTZ83H8ZNnsWvjSuX+2ASsPz58tcdmiGBxi/tSZMqQPka16WPAeujoCYwYNwUey+cjR/asMRoPA9YYcbExBShAAQpQgAIUoIAOBRiw6hCXXVNA3wXE3qr/XvHDibMXIP7F/8fL1NQUpYsVRMWyJZDI3Fzfh8P6EoiAsQaC8TV9xurZ789RuHTVFwe3e0T586tFB1eIP99EqBfxCrhxC+1d+2FQH1csXLYKDuXKYNTQ7ytQYzJHE2fMw3Gvs9izaRUD1p/AHTh8HKPGT8XaZfOQK0e2mBDLoJkrWGNExsYUoAAFKEABClCAAjoSYMCqI1h2SwF9F7j38An2HTmFV0Fv1JaaI2sm1KpSHmlSpdT3obC+BCZgrIFgfE2jsXo2c+6K8PBwbF69JAqt2If0/MUrOHVwe6SfLVi2CmvWb8HuDSsxa8EynDh9Dns2rY60TcCYCdPhF3gjUjirWhnqNn86bPLnhVi9unXnPqXv1s0boXe3jvIvssQWAe2cmuLV6yCcOXcB5uZmqF2jKjq3bw1zM7NfvgY/W8F66NhJrFq7CfcePJB/dteuUQ0d2zkp/apbwTp++lx4Hj2B5XOnKStI/QNuyPDS1z8AFomTwL68HXp16aBsqaDaS7ZTOyc8evI02nEIA2ExY8JouU3Dj5dq9arqc2EnDMUVGhqGFe4bsPuAJ169fo3sWbKgTcsmqOVYWenmx4D148dPcO0/FOFhYVg2b5oybwePHMfqdZtx7+FDpE2TGg3r1JQrmFUHNKr2ph07YjB27jmIa/7XYW2dBi5tnFCzWqVfzgkbUIACFKAABShAAQpQgAEr3wEKJDCBd+8/4NCJs7h+867akadMngyOlcoif67sCUyGwzUUAWMNBOPL31g9Gzq5IEN6ayyZPSUK7ch/pkKEbsf3bkaiRN/3WBWhrPja/Zwp43DsxGn8OWYCJo8djorlyyh9iK+z+wfewMaVi5TPvM54Y9DwscrhUY+fPMWMeUtw8aovpowdgYwZ0iNjemslYDUzM0XZ0iVRslgRnPv3Es79e1EGsCKI/dUVXcB69MQpDB0zEbYF8sl6b9y6g8PHvdCofm0M6ddDdvtjwOqxZQdmL1iGyX//BYf/xihqb9u1j3SoW9MRb96+xZade+Xq0sWzJst+VEGxGEc5u1IoUbSw2nGIcHTOIjf8M2IwShUvGmVob9++w4ZtO7FslYfcqzZ/nlzIkyuHbDdj7hL5s8oVy6NA3jw4deYcfPwC8Pdfg1Cj6rfQM2LAKsJ0Mf7LV69h+fxpyvYJqi0hKpQpjfJlSyHg5m3s3HMg0hYRKpckSRKjXi1HZEiXDnsOHsbdew+wbO5UFLTJ/6tp4c8pQAEKUIACFKAABRK4AAPWBP4CcPgJRyAkNBRnL1zFqX+vIDQkNMrAzczNYF+qKMqULKLRKqqEI8eR6puAsQaC8eVsrJ51mrZDwQL5MG38yCi0U2ctxOade3BohweSWlnJn4tVmy49BuB/fbqjScM6EIdL1W3aDlUrlo90UJUmAavo72d7sBYvUhALZkyUzw0LC0OrTj2RPGkyLJ0bNQz+sfjoAtZu/YbIVbGrFs2CpYWFvG3s5JnYd+go9m1xR/JkSSMFrGIVat8hI+U+tG1bNlEeI0JLcUDXercFsE777dApEUaLUFoErEUK2SgBqwiI5037J1bjUD1Q3R6swr7mH61QrbI9xgwbJJt++fIVzq59YWlhiRULvq1yjRiwLl21DivdN2D2lHEoUbSQMp4uvQchLByydhEIi0vszbv34GF47tggP1MFrJ2dW6OTs5NsIw59bNKmk9y/t2eXDvH168nnUoACFKAABShAAQoYiAADVgOZKJZJgd8RCLh9D57Hz+LNu/dquymQJweqVywr/wWcFwX0XcBYA8H4cjdWz5+tYBV7foq9PyOuYJ23ZAXcN2zFzvVuymn2YkXk+QuX5DYBqpWu2ghYXdq2RNcObZQpF9sOeF+8gl0bVvzyNYguYK3dtC0q25fD0AG9lD48j57E8HGTZSBZIF9eJUgcOaQ/Zi5YCsskSbB17TLlq/LiRjHmO/fuYdSQ73vPvnn7DmJP29FDB8qv6KtWsIowUoSSqism41Ddoy5gvXXnLtp07q08T9VWBON7PY/Ac8d6+ZEqYP1nxBD8OXoCajtWibJnbq0mbVDBrhRaNm2o1Hn2/EUsXL4aOzzckM46reIiwmIRGquuP5xcUKxIIblqlhcFKEABClCAAhSgAAV+JsCAle8HBYxYQOyvuvewF+4/eqp2lHKPvqoVkD1LRiNW4NCMTcBYA8H4midj9YzpHqyN23bGl89f0arZH8pUXPH1w8nT5zBl7HDlK/TaCFi7urSFS5sWynPEPqinTntj18aVv3wN1AWs4hsKFWs1jvS1d9HRhcs+6DlwGKaOGwH7cnZKkChW7VpYWODlq1dydW6d6lWU54qVsFd8/NTW0ce1I1o1a6QErL8zDtUD1AWsqj1RZ04cg7KlSyi1iFWqy1atg+fODbCytJABq/CwsrKUK1vfvnuHtUvnImuWTPIelUt0qD8GzwtnTkKxwrZK8+btu8EmX16MHf6/X84LG1CAAhSgAAUoQAEKJGwBBqwJe/45eiMVCA4JwYmzF3H+8jX59dMfr8SJE6FS2ZIoWdQWpiYmRqrAYRmrgLEGgvE1X8bq2XfIKFz28cXB7R5IZG4eibelS3f5z+Jr8OLy9b+Ozr2iD9Hq1KgKsepTXOKr8ld8rmHbuuVKn8dOnpYrKJfMmYLCtgXk5z/bIuB3gkltrGBNmzo1li+YBhEWP3z0FOtXzFe2ShArWB8+eoJVi2ZG+0qqVrD+zjhUnf/uClbhIfZ3HT10gNxqoVjhgjJQVl1iBWud6lXRr0fnaMej7vAv0ZgBa3z9qcTnUoACFKAABShAAcMTYMBqeHPGiinwUwEf/xs4csobHz5+VtuuqE0+VHGwg5VFEkpSwCAFjDUQjK/JMFbPLTv2YsrsBejr2hFOzb4fHqU6vErsO6raW3P2wuVYv2UHdm9YiVSpUkaaCrGdwKmz55VtAuYudsO6Tdvxf/bOA7zJqovj/zaje0DZe8iWvSlTQAQFUfZeMlUQBXGACz4cDBEEZe8tW6YgQ5Ape+8NZXSP7H7PuSGhI4WkTZO8ybk+fdImd53fuYa8/5z3nPXL5orby6lNmzkPy1avTyWwTpw6E9t27sZfG5abb8G3hzCZkcA6YNiniI6JFTlYfX2M7+/jJvyCrX/txrY1SxAUFGiOYP3h689F8ajLV66h95CPRXGtDwb0EWN+m7sIy1evx5zpE1G6ZAnxHH1Rd/rcRVDuWGr2sMME2VSEyhRNSs+bcrA2a9zAfMs/rdlr8DAolT5Y+NvPYjhFsC5ZuRZb/1iMkJBgrFy3EVOmz8Gk/32FerVriD79h45EVHQMFv4+xSwiU7HHh48eoVSJ4qIPC6zOevfhdZkAE2ACTIAJMAEm4D4EWGB1H1+yJR5OIOJJJLbtPoAHEU8sksibOwwtm9QTlay5MQEpE3BXQdBZPnFXnlTEafDwL0R0aoO6tVCyRFHcvfcQe/75F/ny5cGcqROEKEfV56mYUeFCBTH1p7Hp3GCKTjXdZn/2/EX0H/qpqHZPFefvP4jApm1/iSJMKSNYSfijvK4d2r4FioAtV6aUXYTJjARWk1D5avkyaFivDq5cuyGKU7Vp9bo5L6slIZEKPv259S8smT0NRYsUEvb0GPAh/P39Rb7VwIBAHDh8BJevXsfimVNRpHBBq+0gcXf6rAX4bvSIVLlNU0I+f/Ey+n0wAnVqVkPbt94QeWSpTZo2E39s2IymjcJRtnQp7D94GKfOXkiVlzVlkSsaQykBeg0YBrqLY+mcaSJv7s69+zFm7E8o/UoJNG5QD0lJSdi5ex/kCgWWzZ0uijqywOqsdx9elwkwASbABJgAE2AC7kOABVb38SVb4qEEktQa7D1wFKfOX0ayBQaUp65xvRqoWK4UOBmAhx4SNzPbXQVBZ7nJnXnGJyRi0fLV2LV3P548jQTlna5Xpyb6du9kLmR14dIV9H3/E3zxyYdo3bJ5OjeQcNq6c280rFcbo0cOE69v2fE3FixbhaioaFQoVwbNX2uIcT/9gvkzJqNs6VdEn9jYOHw59kdQHtd2bd4E5S8l0bdRq/YY3K8nenRuZ16LRM5/Dx3FhhXzX3oMKFKWImbXL5+LvLlzp+pPguqiZX/g9r17yBESgpavN0G/nl2FiEjNlNs0pRAcHR2DLv0+QIVypc231hMTimQ9f/EKAgP8UbZsKfTt1kmIlNTIjsZvdsCgvj1eaIcpinjy+K9Rt1b1DG2j4lXb/96DggUKiIJc1PR6A+YvXYEt23fhaVQ0ChcsgG6d2qXKFztr/hIsXb0Oe7esMc997MRpDBv1lYhOpshcalTQbMmKNbhz7z7y582DShXLY3DfHkJgz4gLPU+pJMqXLpWucNZLncQdmAATYAJMgAkwASbABDyOAAusHudyNthdCFDU1YkzF7Hv0HGoNJp0ZlFuVcqx2rBONSgVCncxm+1gAnBnQdAZ7mWezqDOazIBJsAEmAATYAJMgAkwASbgTgRYYHUnb7ItHkPg7oMIbNv9L55ERlu0uXCBvHijST2E5Qj1GCZsqOcQYEHQvr5mnvblybMxASbABJgAE2ACTIAJMAEm4HkEWGD1PJ+zxRImkJCQhJ37D+PClRsWrQgKCkDT+rVQtmQxCVvp2lvv/+EIdO3wjrhllW63/fHbL8wbpttQf5+3GA8jHmHW1J/M1cRNHTZs3o4ffp4uboEtU8p4G7GtjYrtzF28Ajdv3Ubu3LnwVotm6NK+LWQyb/NUVJBmwdJV2LR9p7iFuWjhQujTraPIP5iy0a3B0+csxNH/TiJRpUL5MqXwwcA+eKX48/OTkb1UJOa3uQvxz79HoNFqUaViBQwb1A8F8ue11SSb+7MgaDOyFw5gnvblybMxASbABJgAE2ACTIAJMAEm4HkEWGD1PJ+zxRIkoDcYcPTEWew/ego6nS6dBZRfr1a1igivXgkyuTHXHrfsIdBnyMfo1vEdPImMwrHjp8w5CynXY5tOvVGoQH60aNYYb77+Wqpq5FQVu0PPQahSsRzGjRmVqc39d/I0PhgxWlTyrl+3Ns5euCQK9gzo010IqKZGhXWowA4JqpQzcd+BQ7h05Rqm/PANalWvKrpRMZjegz7C3fsP8E7rlggKCAAJwLFx8Vg2b7rIU0gtI3tHjhmHw8dOoP3bb4rK3Ks3/ImQ4CBRBEepzN6UFCwIZur4ZDiIedqXJ8/GBJgAE2ACTIAJMAEmwASYgOcRYIHV83zOFkuMwLWbd7Fz3yFExcZZ3Hmp4kXQvGFtBAcFSswyaW43I8Hx8pVr6DV4eKoK1yktnL90FeYtWi7ESyrWkpn26ZhxOHn2PNYvmwcqXkZt+Off4NKV69jyxyLxNxWfad62C2rXqGaOrk1ITETnPkNE1fMpP3wr+m3duQff/TAZ33/9mTmy9cHDCHTqMwStWzbDyKGDMxRYqd+73fuLyFkq3ENt555/MGbcBEyfNB7VKr+aGfOsHsOCoNWorOrIPK3CxJ2YABNgAkyACTABJsAEmAATYAIZEmCBlQ8HE3BRAtExcdi6+wBu3X1gcYc5QoLR8rVwFCmYz0UtcM9t3bv/EDlCQ0QkcaJKjXx5cglDTdGlv/z4rTlK1EQgJiYW7XsOQIumTTBi6MBMgzl7/iISEpNQu4YxCpXazPmLsWDpauzZ/Ad8fJS4eesuuvQbIqqU9+zS3tyPIl/v3ruP9cvnieeoCvnq9ZuxZ/NqeHs/Ty8w6KNRSKZ5p/wo+lmyl6qqHz91RqQUMFXhPnHqLIZ88gV+/O5LUW09OxsLgvalyzzty5NnYwJMgAkwASbABJgAE2ACTMDzCLDA6nk+Z4tdnIBOq8P+oydx9OQ5UGqAtE2hUKBBrSqoUbl8KmHMxc1y6+0dP3UW73/yPBcrGTt72gRzDtYpv83Bpi07sHrxLOQMtVx4bPe+A1i1bhNu3L4LrUaDAvnyoXvndmjRtNEL2X3y5Xe4cesO1i6ZLfpdunIVvQd/jBEfDkS7t980jx319XicPHMO29cuFc9NmjYTG7fuwO4/Uwusg4d/BpVag/kzJtvks+8n/4qtf+3GumVzEJYjh01jbe3MgqCtxF7cn3nalyfPxgSYABNgAkyACTABJsAEmIDnEWCB1fN8zha7MIHzl6/j7wNHQfk8LbUKZUvitfBaCHh2e7gLm+JRW0tMUmHTth2YMn0Ohg3qi3Jly6BMqRLw9fHBg4hH6NR7MPz9/SCXySGXeYtb8gf27Q4/X+Nt/tTGjP0JSh8lXi1XVvy95a9dOH/xCpbMnobiRQtb5Hnm3EUMGPYp+vbojP69uoo+pue+GjUcLZs3MY+jdAB79h/C33+uEs+t27QNP/0yI1XE6cNHT9Cp90C81iAcX3/+sdU+PHnmPIZ8/LnITft+/95Wj8tsRxYEM0vO8jjmaV+ePBsTYAJMwJMIJCfTfS/WNy8vL+s7c08mwASYABNgAhIiwAKrhJzFW3VfAo+fRmHL3/vxIOKJRSPzhOVAq6b1zbejuy8J6VpmimKd+tNY1KxW2WzI1N/nYfkf61GxQlk0rFdHFJuifKVNG4W/sNgVCbPvdnsPoz8dhjdfb5oODInwvQYNA13XLJ0zzSzWmm7VH//VKDRpGG4eR2Lqn1t3Yt+2teI5EoW79h0iilq1e7sVggIDsf7PrXgQ8RgTxo5G/bq1rHIG5XftMWAYfHwUWDBjikhTkN2NBUH7Emae9uXJszEBJsAE3JVARmKqtSKrJXGVBVd3PS1sFxNgAkxA3icLAAAgAElEQVTA8wiwwOp5PmeLXYiAWqPFnn+P4uS5y7D04dTP1weN6tZA5Qqlwd/3u5DjLGwlI4G1dafeyBESgvm//QyZzJjrlG7P/2PDZqxa+HuqglcqtRoREY+RpFKBzgblQx025D10frdNuhW//O5H/PPvYfw+5QeUL1va/Lo5gvWzj9GyWWPz89/9+DP2/HPQHMFKL9x/EIGfZ8wWqQNoj/cePESRwgWwZNav5r2+jPrshcswb/EKzPl1AiqULfOy7nZ5nQVBu2A0T8I87cuTZ2MCTIAJuBOBlJ9PTb8rlXIoZDJ4e3lB5k2fUL3wssBUGmswJMOQnAyd3gCNTg+DwYC0AisLru50etgWJsAEmIBnEWCB1bP8zda6CAH6kHny/GXs+/cYktSadLuiD5dVXy0jxFUfpcJFds3beBEBSwIrRZk2f7sz3uvZFf16djYPp1vqKdfpD19/jkYN6ornSahcumotqIBUymZJYF2zcQsmTv0dwz/oj45tW6fqf/HyVfQZ8vIcrGltOXDoKEaMHmtzkaoPR45GZFSMiKJ1VGNB0L6kmad9efJsTIAJMAF3IGASU+mRimH6KGRQyGWQpSiMmVU7aW69IRlqrQ4arS6V2MpCa1bp8ngmwASYABNwNAEWWB1NnNfzeAL3Hz4W6QCeREZbZFEwXx680aQecodlb6Egj3eEnQFYElgTE5PQtE0nkR+V8qSamklgnfS/r1Cvdg0cP3UG73/yJQb17YFmjRugYIF8oGjWJm92SBfBevnqdfQfOhL1atfE919/ls6Km7fuoku/IRjyXi/06NzO/DoJobfv3MOGFfPTjaEIkp4DhyEwwB+/T/nRJjILl60W0Sh9unW0aVxWOrMgmBV66ccyT/vyvHbjFnoMGCpyII/59KN0k586e0FEp6dslK+5aJHC6NSuTarI86GfjsGjJ0+xYt6MDDeZUZ9zFy+J95X6dWq+MB2Jfa03zjZr/hIsXb0Oe7esyY7peU4mwASykUBKYVUul8FPqRD547O70bpavQFJam2qu7pYaM1u8jw/E2ACTIAJ2IsAC6z2IsnzMIGXEEhIUmHX/iM4f+maxZ6Bgf5oGl4L5UoVZ5YSJJBRioD2PQfA388f82dMNt92//Ovs7Fq/SasWzZP5NWldAGUNmDnxhUI8PcX1t+5ex8dew9KJbCSYNt7yHBxS938GT8jKDAgHSmtVotmb3dG3do1RIQsNRrXue8QFC9aBL/8+G26MZt37MK4n37BrF9+ErliXb2xIGhfDzFP+/KcOX8xFixdLQrbbf1jCZRp7kIwvVc0DK+DUiWN7/eUy/jIsZO4fvMWhg7qiy7t24rnh3zyBR4/eYrVC2dmuElLfWJiYtF78EdQ+vhg3vRJ5vcV+1qa8Wwz5izEstXrsH/7ekctyeswASaQRQIphVWKVCVh1ZTaKItT2zyc0gckqp7f0cMiq80IeQATYAJMgAk4gQALrE6Azkt6FgESw46ePI/9R0+CxK+0jT681qzyKurXqAy5Qu5ZcNzI2owE1m279uDb7yejSsXyIEHlytXr2LpzD9q+9QZGfTREEDh99gIGfjQK4XVqommj+tDpdFi97k9cuX4jlcD6v4lT8ee2nWjXuhXKlCrxnJ6XF95o3gQKufH8TJs5D8tWr0ezRvVRpvQrIvcqRbNNHv816taqnoq6RqNFp94DUaZ0KfzwjVGQtaVRqgOdXo/ZUyfYMixLfVkQzBK+dIOZp315duw1CLHx8SCR88fvvkTDerVTLWB6r/j684/xRtPneZL1egMGDR+F6zdvY+eGFeJW2cwIrCSSfPLldzh15hxmT5uIEsWK2NdAK2ZjgdUKSNyFCbgIgVQRqzIZ/HwcE7H6MvOpiGeCSg2tTm9OHcBC68uo8etMgAkwASbgTAIssDqTPq/t9gRu3rmP7XsOIiom1qKtJYsWQvNGdRAaHOT2LNzdQNNtv9MnjUe1yq+mMnfn3v1YvPwPEZWaK1dOtGzWBN07tzMLotR5w+btWLJqLZ4+jUKxooXRp3snfDN+Iga/1wvt335TzNdzwDAhulpq29cuRfCzc0RCzbwlK7B5205ExcSIQlp9unVC08b10w1duWYDps9eiMWzpqJokUI2u4kiY/V6/Qsj7Gye9CUDWBC0L1HmaT+elMKj16CPMGLoIPw+dxHq16kFElJTtowEVuqzZOVaTJ+9AGsWz0aB/HkzJbDOX7ISsxYsxdgxn4ovWZzRWGB1BnVekwnYTiCluOrvo3DJvP9UECtBpXFK2oC0BWhZ4LX9jPEIJsAEmIAnEWCB1ZO8zbY6jEBsXDx27D2EqzfvWFwzJDgQLZuEo1jhAg7bEy/EBNyFAAuC9vUk87Qfz9/mLhIi6eZVC/HLb3Pxz8Ej2PLH4lRpAl4ksE6ZMQcr127EXxtWiJzItkawHj1+CsNGfSVyuQ4b1C+dYfTly/ylK7Bl+y5ERseIvK99u3VEo/rGYnujvh6PS5evYu3SOaKojam998FIKH0UmDFpPNZt2oaffpmBn7//BnVqVrMIL63ASmlKBg3/HMkGA+ZOn2Tm8dfufVi8fA1u37uHsJw50Kbl6+jZpb2IVrt87Tp6DfwIn3/8Adq0et28zsEj/+HjL77F9En/Q7XKFe3nPJ6JCXgQgZTCobeXFwL9fODt7eWyBLI7mjWtkJoZECy+ZoYaj2ECTIAJuBcBFljdy59sjZMJ6HV67D92CkdOnAFdyKZtdAt3eK3KIiWAPauwOtlsXp4JOJQAC4L2xc087ceTci7nz5sH0yaMw95/DuKzb7/HT2NHo0HdWuZFTALrV6OGi0JY1BKTVDh4+BjGTfgFZUuXxG8//yCet0VgJfGz16DhiIqOxoSxo1E/xZqmxSnX85qNW9D2rRYoUawo9h04hGMnToMK7lH6EEpf8t0Pk0Wxu8qvlhPDHj56gne69jWnK6GczdNmzsf/xnyK6lUqWYSXUmAl4eLzb3/AqTPnMW/GJMGH2t979+PLsT+hXq0aqFu7Oi5fu4FNW3YIgXVwv56iT4deA0X/qT+NNa8zftI07D1wCJtXL4JcJrOf83gmJuAhBFJGrVKaqiA/X3i5rraayitJGi1Uaq1dUgakFFVNv1NRL6VcJj6jExISTU1sSORNpv/oMTkZGr0eOp1B5MVPK66y2Ooh/zOxmUyACTCBNARYYOUjwQTsRODi1ZuiiFVcfILFGcuVLoFm4bUQEOBnpxV5GibgmQRYELSv35mnfXhevHwVfYZ8jJFDB+PdNi2RpFKhVbseaNKgLr767HmaAJPAamnVIoULYuLYMShcyHh3g7UC68OHEciTOxfuP3wEgyEZIcFBWDzrl1RRqBRF2uKdruj4bmt8OLCvmF+r06HP4OEIy5lTFMCjPq069EDbN9/AR0PeE32oIB8V5lu/fC7y5s5tFayUAuucRcuxcOkqTJ0wDlUrVTCP7//hCBiSIYrrmQrp/DhlBrb+9Td2bVwlnqNUBwuXrRYRwaGhIULIeLNDLzSqXwefDX/fqr1wJybABFITIHGQfqiQFUWuSq1RAayEJHWmRNa0oioJqr4KuXi/oUjezDSaU29IFrli1VqdYJtSYGWxNTNUeQwTYAJMQJoEWGCVpt941y5E4GlUNLbsOoB7Dx9Z3FWunKFo9Vp9FMhn3YWpC5nGW2ECLkmABUH7uoV52ocn5U5dumodNq2cLwRLahS5eez4SZEmQKFQiOdMAisVvStVsrh4ztfHR+RArlOjqrkfPW+twHri1FkRzTlj8ve4fvMWfvh5Or4cMRRvvdHMbNy1G7fQvf+H+GhwP1Su+FzoXLj8D1y7fhOrFv4u+o4e+yPOnLuI9cvnCZHggxGjodNpRVSrtc0ksP5vzCh89s33ophX2ly0Ld7thno1q4t0BqZ2+NgJ/D5vMTaumI/cucJw49YddO33Pr74+AO0bvU6Tpw+hyEffy4iWmtWq2ztdrgfE2ACzwiYxFUfhRz+vkrJciEhM1GleRZh+nJhNKWwSu9rVMhLIZNlS+Su3mCASq2DRqfLlAgsWafwxpkAE2ACTAAssPIhYAKZJKDRarH34H84ceYiDHS/UJrm66NEozrVUeXVMuluHcrkkjyMCTABACwI2vcYME/78Hyn+3tQqzTo0v5t84Snz13A/oNHUt2y/6IcrGl3YovAOuLDgWj39psiPU3X995HUpJKiKYk3lI7evwkhn76lUVj/f39sGvjSvEa3X7/2dfjMXvaBBQpWEBEtH44qC86vfNcCH0ZMRJYF69YA5rXz9cPsXFxWDbnVxQqmF8M1en1aNDinQynWfDbZJQp9Yp4vefAjxCWM1TkfJ3y2xxs27kHm1ctMke9vmwv/DoTYAJGAlKPXE3rx5TpAjKKEk2ba9bPVwmF7Hl+6ew8G3RtQOkMSAw27c+R0awZ5ZV15B6yky/PzQSYABNwRQIssLqiV3hPLk2ApNTTFy5j74FjSFSp0+2VvkevUqEMGtarAT8f6UYHuLQTeHMeTYAFQfu6n3lmnee5i5dAhaAyapRrlXKuUssOgZVSBKxdOte8/J5//hXRs4P69kCvrh3E86YI1h++/QKNwutkuFetVotWHXqiTcvmKFm8GMb+NAUbVsxDnly5rAZlElgpR+s3n3+MLv3eR+VXy2PiuDHmOSiCtWWzJuZUBBlNTkXDZs5bLHKu9h7yMWrXqIpRHw2xei/ckQkwgefiKuUWDQ7wdRsk8UlqcWu+MVdq6kjWlLlmfRQK+Psa7yJwdKO0LQlqDXTP9knr21vkfFGRLtNrL1vzZa87mhuvxwSYABOQIgEWWKXoNd6z0whQsY8tu/bj0dMoi3vInzeXSAeQOyyH0/bICzMBdyfAgqB9Pcw8s85z6u/zsHLtRnOu0JQzfj1+Iv49fMycJiA7BNbHT55i9cKZqQwhwffm7Tv4Y9FMkb+UCmm93rYzGtevi3FjRpn73rl7H/7+vua0BvTC/yZOxbGTp1G6RHERfWoqumUtKRJYSRjd+sdihIQEY+W6jZgyfY4oplWvdg0xTf+hIxEVHYOFv09BgL+/eI5ymD989AilShhTJ1B7EPEY73brh07vthGMqYBYjaqWi2tZuz/uxwQ8iYApcpUecwT5213cczbL2AQV6LZ8SwIhPRfgq4TcQVGrL2Kh0xuQoNKkKoqVFVEzbT5Zb29vUOoHb28vkU9WFOnyNj6aGt1wZ7rrjh71+mSRyiBtoa6s7MvZ54HXZwJMgAk4kwALrM6kz2tLhgBFqu4+cARnLly1uOcAfz+8Fl4TFcqUlIxNvFEmIFUCLAja13PMM2s86SKXBMDChQqmqnZvmnXv/oMiDylFb4bXqZktEayWBFaTkNuxbWsM/6C/2M7EX37Hmk1bxD6qVa6I+/cfYstff6Np4/oiZ6upHT1+CkM/HSMEi+Hv90eHtm+ZX9v6125Mn7UA340eIeaw1FIWuaLXKSVArwHDRFGtpXOmiTyzO/fux5ixP6H0KyXQuEE9JCUlYefufZArFFg2d7rIKWtqgz4ahdPnLiI0JASbVi7g9ABZO7I82oMImEQ4EtCCAvwcdnu8IxGTuBoTn5QqipXsJlE10M83W/KsZtY+2ld8kka8J2YmbUBaUZUikklUpYJlJKxmthFDirBVafUstmYWIo9jAkyACdAXW9HxSemTRzIaJsAEBAH6QPrf6Qv45/AJUM7VtI2+La5ZuTzq164KhVzO1JgAE3AAARYE7QuZeWaN54VLV9D3/U/wxScfonXL5ukmU6s1aN25NxrWq43RI4fh1NkLIMFw7OiRaNa4wQsXJ5Hz0ZOnWDFvRob9XtTn0zHjcPDIfyIXa/58ecVF/fwlK4WoGhMdixLFiiK8Tg307NIhlWhJ//a16dQHkdHRouBUrjBj0S5qazduxYSpv2Hy+K9Rt1Z1i/uaNX8Jlq5eh71b1phfP3biNIaN+grv9++Nrh3aiud3/L0PS1aswZ1795E/bx5Uqlgeg/v2EFGvKduaDZsxcdpMvNumJUYOHZw1h/FoJuBBBMx5V2UyBPob8zG7Y0tSa5GkNha9Ipt9lZQSwHXTdKk0tF+tTSJrypQHSqUcfgpFlkTVjM4BpTRQaXVQa2zbnzueK7aJCTABJmArARZYbSXG/T2GwO17D7H17wOIiom1aHPRQvnRskk4QkOCPIYJG8oEXIEAC4L29QLztC9Pd5ntw5GjxW23MyaNd7pJJ8+cx+Dhn2H6pP9lGDXr9E3yBpiAixFImRogNNA/W8Q4VzGZbn2Pjk8UgRH+vj7w83FOvlVbeFhTpIvmSymsknDsq5Q7JM0DrUsisLOKdNnCkvsyASbABFyFAAusruIJ3ofLEKAccH/tO4TL129b3FNoUBCaNayNV4oXdpk980aYgCcRYEHQvt5mnvbl6Q6zPXgYgU69B+OTDwfi7TdbON2k7yf/ikNH/sO6ZXNBd45wYwJM4MUEUhd4krt0NKe9fKnS6MSXQpRzVSqNBEyKZn1ZkS65XIZAX6VDhNW07Igp5Y7V65/nueUcrVI5YbxPJsAEHE2ABVZHE+f1XJaAXqfHoRNn8O9/p0G/p21yuRz1alRCraqvpsoN57IG8caYgJsSYEHQvo5lnvblKfXZtu3agxV/bETEo8dYu3Q2/HydV3H83v2HWL95G5atXo8h7/VCt47vSB0v758JOIRAqujVIH9R9IibaxKIT1JDq3uekzXlLkW6Ax8F/JTOj8iNV6mh1WYud6xrkuddMQEmwATsT4AFVvsz5RklSICiVXftP4yY2HiLuy/7SjE0rV8LQYEBErSOt8wE3IsAC4L29SfztC9Pqc/2Tvf3hAlffjIUNapWcqo5m3fswk9TZqBx/boYM2o4f7npVG/w4lIiYM69SpGPfu6be1VKPslor5TeICYhSaQCSBkZSn8H+vu6VGEyysuaaGPuWHfwEdvABJgAE7CWAAus1pLifm5JIDI6RuRZvXM/wqJ9OUND0KppOArlz+uW9rNRTECKBFgQtK/XmKd9efJsTIAJMAFnEkgZvRoc4Ae5jNNqONMf1qxNt+HHxCeZBVbyYUiAX6rig9bM44g+Wr0B8Ykqmwp0OWJfvAYTYAJMwBUIsMDqCl7gPTicgFanw75Dx/Hf6QsiIX7a5qNUoGHt6qhaqSzfVuVw7/CCTODFBFgQtO8JYZ725cmzMQEmwAScScAksNLn25zBgeDsAM70hvVrJySpRT5WaiGB/i4tjGu0eiSo1BZzx1pvMfdkAkyACbgfARZY3c+nbNELCCQDOHfxKnYfOIqEJJXFnpXKlULj8JqiCik3JsAEXI8AC4L29QnztC9Pqcx28dpN7Dt4XGy3Yd1qKFuymFS2zvtkAkzgRZ91k5NF8IBM5i2iILlJgwAJ409j4hEaFODS4qqJJonBVKTLUoEuaRDnXTIBJsAE7E+ABVb7M+UZXZRAxJNIbNm1HxGPn1rcYd7cYWjVtD7y5srpohbwtpgAEyACLAja9xwwT/vylMpsc5auw5OoaLHdXDlC8V43LiAlFd/xPplARgRSpgcI9POFUiFjWBIiQKkCZN7SSemQsvBVyvyxEkLOW2UCTIAJ2JUAC6x2xcmTuSKBJLUGe/YfwekLV0ARrGlbgJ8vGofXwKtlS4FrrLqiB3lPTCA1ARYE7XsimKd9eUplNva7VDzF+2QC1hNImR4gNMhfUmKd9VZyT1ciEB3/vEAXi6yu5BneCxNgAs4gwAKrM6jzmg4hYEhOxokzF7Hv0H+gqpdpm7eXF6pXKocGdapBqVA4ZE+8CBNgAlknwMJQ1hmmnIF52penVGZjv0vFU7xPJmA9ARJYKT0A/YSFUP5VDh2wnh73zAwBnd6A2IQkeD+LvOUzlxmKPIYJMAF3IcACq7t4ku1IReDugwhs2XUAkdExFskULpAXLV8LR87QECbHBJiAxAiwMGRfhzFP+/KUymzsd6l4ivfJBKwjQOIqNZPAmis0yLqB3IsJZJFAXKIKJLRyPtYsguThTIAJSJ4AC6ySdyEbkJJAQkIS/vrnEC5evWkRTHBQAJo2qI0yJYoyOCbABCRKgIUh+zqOedqXp1RmY79LxVO8TyZgHYGU+VdJZGWB1Tpu3CvrBPR6A2ISkswCK0exZp0pz8AEmIA0CbDAKk2/8a7TENDp9Th64iwOHDsNnU6Xjo9MLkOdqhVRr3ol0O/cmAATkC4BFobs6zvmaV+eUpmN/S4VT/E+mYCRgClCNS0Pk5iVMv8qCay5cwQzOibgMAKci9VhqHkhJsAEXJgAC6wu7BzemnUErt68g537DiM6Ns7igNLFi6B5ozoICgywbkLuxQSYgEsTYGHIvu5hnvblKZXZ2O9S8RTv01MJZCSo0vOWIgRTRrDS6zmD+XOvp54dZ9it1uiQoFJzLlZnwOc1mQATcBkCLLC6jCt4I7YSiI6Jw9bdB3Dr7gOLQ3OEBIs8q0UK5rN1au7PBJiACxNgYci+zmGe9uUpldnY71LxFO/TkwikFFXpd7lcBh+FHFSYVeadumAVZVw1iqqA3mCAVqcXP3q9XuRhzZOT6wx40tlxtq10BqPjEoXAyrlYne0NXp8JMAFnEWCB1Vnked1ME9DqdNh/+ASOnTovPlCmbUqFAvVrV0WNSuXM36JmejEeyASYgMsRYGHIvi5hnvblKZXZ2O9S8RTv0xMIpBRWSZzyVcihUMiEsGpro8/GKo0WAb4+tg7l/kwgSwSeRMdBJpOxwJolijyYCTABKRNggVXK3vPAvZ+/dA27/j0KKmZlqb1a9hW8Vr8W/PlDpQeeDjbZUwiwMGRfTzNP+/KUymzsd6l4ivfp7gRM4ioJq/4+Cii4VoC7u9xt7YtLVIkoaopipcbFrtzW1WwYE2ACGRBggZWPhiQIPH4ahS1/78eDiCcW95snLAdaNa2PfHlyScIe3iQTYALWEfjv9Hn8te+wdZ2f9XqnZROUKVnMpjGe3JmFNs/0PvvdM/3OVrsOAZOwSo8+SoUQV7kxASkTSFJrkfgsDyunCZCyJ3nvTIAJZJYAC6yZJcfjHEIgSa3Bvn+P4eS5S6BcU2kbRao2qlcTlcqXgu03UTnEBF6ECTCBLBC4cfseVm7cYdMMHVo3R8mihWwa48mdWWjzTO+z3z3T72y1axBIGbUa6KeE7FnEn2vsjnfBBDJHgKJXYxOSOA9r5vDxKCbABNyAAAusbuBEdzSBPniePHcZew8eg0qtSWcifStatWJZNKpTXXzrz40JMAH3JbD7wFEcPnEWxm9Zkumes9TGUoUP+orFC6hd7VU0qVfTfWFkg2UstGUDVAlMyX6XgJN4i25JwFiYKlncPh0c4JupPKtuCYaNkjwBnd6AmHgudCV5R7IBTIAJZJoAC6yZRscDs4vA/YePRTqAJ5HRFpcomC8PWjUNR1iO0OzaAs/LBJiACxGgC9Fl67fizr0Isatncmq63wsXzIuubVtyzi8bfcdCm43A3KQ7+91NHMlmSIpASnE1JMCX/72SlPd4sy8joNPrER1nFFjph3OwvowYv84EmIC7EWCB1d08KmF7EpJU2PXPYZy/fN2iFUGBAXitfk2Ue6W4hK3krTMBJpAZAkkqNeYuX4/4hESAIlbTRLEGBwWgT6e34ccF7mzGO2vpWkRGxYhxOXOEYEC3d22egwdIjwALrNLzGe9Y2gRM4io9hgT6cVoAabuTd2+BAEWwRsclsMDKp4MJMAGPJcACq8e63nUM1xsMOHryHA4cOQmtTpduYzKZN2pVeRXhNSpDrpC7zsZ5J0yACTiUwMPHT7D4j83Q6/SpBFZ6j+jVsTXyhOV06H7cZbELV2/gn8MnhDkNalflL7HcxbEvsYMFVg9xNJvpEgRMOVcNBgOC/H2hkMtcYl+8CSZgTwJ0HRcTb8zByhGs9iTLczEBJiAVAiywSsVTbrrPm3fuY+vuA4iJjbdoYclihdCiUV0EBwW6KQE2iwkwAVsInLt8HZt27E01pPXrjVChdAlbpuG+TMDjCbDA6vFHgAE4kIApelUu8xYCKzcm4I4EktRa0B2JLLC6o3fZJibABKwhwAKrNZS4j90JxMbFY/veg7h2867FuUOCA9GySTiKFS5g97V5QibABKRNYPuegzhx9qIwonql8mjesLa0DeLdMwEnEGCB1QnQeUmPJJAyNUBooD+8vdMUavRIKmy0OxKITUiCRqtjgdUdncs2MQEmYBUBFlitwsSd7EVAp9Vh/7FTOHryLPR6Q7ppFXI5wmtXQc3KFTg3lb2g8zxMwM0IUFqR5eu2ws/PF++0fI0rMLuZf9kcxxBggdUxnHkVJvA8elWGIH8fBsIE3JbAo8gYyGQyc3oALnLltq5mw5gAE8iAAAusfDQcRuDClRvYdeAI4uMTLa5ZvnQJNG1QGwF+fOuUw5zCCzEBJsAEmIBHEmCB1SPdzkY7mEDK3KvBAX6gFAHcmIA7EqAvvyNj4lNFr7LA6o6eZpuYABN4EQEWWPl8ZDuBp1HR2LLrAO49fGRxrVw5Q9HqtfookC93tu+FF2ACTIAJMAEmwAQAFlj5FDCB7Cdgil6l4lY5gwPhxdkBsh86r+AUAokqNRKS1CywOoU+L8oEmICrEGCB1VU84Yb7UGu02HvoP5w4cxGmb/BTmunno0SjujVQuUJp8DecbngA2CQmwASYABNwWQIssLqsa3hjbkSAPv+SuOrt5YXQIH83soxNYQKpCUQ8jTanB6AiV9T4+o5PCRNgAp5GgAVWT/O4A+xNBnDq/GXs/fcYklTqdCvSP7YkqjapVxM+SoUDdsRLMAEmwASYABNgAikJsMDK54EJZC+BlMWt/HyV8OPPvNkLnGd3GgGtTo+o2PTpAVhgdZpLeGEmwAScRIAFVieBd9dlHz56gi279uPR0yiLJubPm0ukA8gdlsNdEbBdTIAJMAEmwARcngALrC7vIj97xYkAACAASURBVN6gxAmkTA8Q6O8LH4Vc4hbx9pmAZQIkrpLISpGr9EPCqiVxlQVXPkFMgAm4OwEWWN3dww6yLyFJhd0HjuLsxasWVwwI8EPT8FqgQlbcmAATYAJMgAkwAecSYIHVufx5dfcnkFJgDQrwg1Iuc3+j2UKPJJA2FVxyMpCMZOgNydDrDVBptOkEVxZbPfKosNFMwO0JsMDq9i7OXgMpr9SxU+ex/8hJaLTadIvJvL1Rs3IF1K9VBXL+5j57ncGzMwEmYDWBZPrQT7nxkg0w6I2PdCFgoJ9kA8TrBoO4MKBH+lv0NRhgoAsH49WDuICgtCjGv73Eo/ib/ktOBtUzMV5ke5l6grqamukCgwqfeNF/NIAiP+jB/Df1Nr4mXvGCyOfnTY8ULeLlDS9vL9D7rUxm/NtbRq97Q+btBW/6SfkczU+DuXk0ARZYXdv9cYkqPHoaDZVaC0PKNw3X3jbvzokE6N+AAD8lCufLhRyc79WJnuClLRHQ6Q1Qa3XQaHWpxFYWWvm8MAEm4E4EWGB1J2862Jbb9x5i698HEBUTa3HlooXyo2WTcISGBDl4Z7wcE2ACnkLAGB2hh46ETxJDnwmiOnpOr4den/zs0SiOklhKH/K5QQiychmJsN7wltOjDHKZF+Qymfl3es742vO+zM49CLDA6rp+JHH15r1HrrtB3pnLEyhfoiByBge4/D55g55HgL50JqFVpdGZjWeR1fPOAVvMBNyVAAus7urZbLQrNi4eO/cdxuUbty2uEhochGYNa+OVYoWzcRc8NRNgAu5OgIRQyuml1emg1eqh0WmNj1odtCSg6vSZRkAf5k0RnxTlSZGf4u9nUaCpf0/9ujG/mLE6rjHg1JhrLGWEqfk58+vPI1JNFxKmyFcR/CqiXI2hrcbfn0fBPv89xWvPKlOLKFsRaZs64jZl9O3z34236omI3CxExMnlMihkMigVcigUMijlCvGokMuhkJNIa6wezM21CbDA6rr+uXbnIRJVGuQKDUTR/Lng56N03c3yzlyGQJJag1sPnuBJdDyCAnxRuVQRl9kbb4QJWCKg1uiQqNaYI1pZaOVzwgSYgNQJsMAqdQ86cP96nR7//ncah4+fERFhaZtcLkd4zcqoWaWCiIDixgSYABN4EQHS+EgsVWk04jZYLd06piPhlB51qW6lz2geEVkpBD/jI733KOQUbWn8Pf1rxufFrfge3Ig9vY+TgC2ifUnI1hvEoyn6V6ujaN/Ur5E4+7JGF0gktArBVSEThV18lAr4KpVClPV09i/j56jXWWB1FGnb1zl79Y74EqRa2WLw92Vx1XaCnjuChPnjF2+KL7rqVHzFc0Gw5ZIhQF+mJ6g05i9+WWSVjOt4o0yACVggwAIrHwurCFy6dgu79h9GbFyCxf7lXimOZg1qg4pZcWMCTIAJpCVAQp5KrRFRWWoSVDU6qDXp8zanHEe5Q32VCrNA56OUw0ehEGKd+F2pEBGk3BxHgIRZtVYLijoxP2qe/21Nvkij2CqHr49SRObRIwmy3BxLgAVWx/K2ZbUzV4x3CNWvUtqWYdyXCQgC+09e5vPDZ0FSBOizRXySSqRwMt0BJCkDeLNMgAkwgWcEWGDlo/BCApHRMSLP6p37ERb75QwNQaum4SiUPy+TZAJMgAkIAvQBOVGlRmKiGkkaDZJUalFAKm2j2/JJQPXzMUY3mkRTk5DKt5pL80AZC1k8E12fia8UpZyk1opIZUtRsBSJ7OerhJ9SCX9/HwT4+Yh0DdyyjwALrNnHNqszs8CaVYKePZ4FVs/2v5Stp/zTLLJK2YO8dybABFhg5TNgkYBGq8U/h47jv9MXLFavJTGkYZ1qqFKxrKhmzY0JMAHPJUC3ssbGJyE2IQmJSWpxe3/KRu8Q/n4+CPL3RSD9+PmIqEUWUD3zzNDFE+UKTEhSIz5RBbqgot/TNqVcLsTWYH8/BAf6pao67Jnk7Gs1C6z25WnP2VhgtSdNz5uLBVbP87k7Wcwiqzt5k21hAp5HgAVWz/P5Cy2mGLMzF69g74FjSEhSpetLQkml8qXQOLwWF13gs8MEPJwAfQiOio0X4mrKokkUeUiCWEigP0IC/BDo78PimIeflZeZT+cnLlEtRPqY+ETExieminqmWwbpTOUMCkRggO/LpuPXrSDAAqsVkJzUhQVWJ4F3k2VZYHUTR3qwGdHPPldyugAPPgRsOhOQKAEWWCXquOzYdsSTSGzZtR8Rj59anD5v7jC0alofeXPlzI7leU4mwAQkQCDZkIyouAQ8jow1R6rSLf3BAX4IehZpSBGq3JhAVgnEJ6kRl2CMjCYRX601RkZToazcOYKRIziAhfssQGaBNQvwsnmoqwusBk0EvJWcGiqbj0Gmp2eBNdPoeKCLEKA7Xejffu9nqYK48JWLOIa3wQSYwEsJsMD6UkTu34FyJe45cBSnL1yxaGyAvy+a1KuJCmVf4YIy7n8c2EImkCEB+rB7L+KpyI9FRYny5AhGvlwhHM3OZ8YhBKhAWkRkDCKexkKn14sUEwXzhglxn5vtBFhgtZ2Zo0a4ssCa9HAp1E/+RHDpn+GtzOcoJLyODQRYYLUBFnd1WQKJKq3I524SV1lkdVlX8caYABNIQYAFVg8+DobkZJw4fRH7Dv9nsZo3fWtYo1I5NKhTDQq53INJselMgAncfvgEMXGJQtQqnDcMBXKHcvQgHwunEKB0AvcfR+N2xFPo9QaEBgWgcL4wp+xFyouywOq63nNVgTXh1lRo4w7CJ9db8MvXzXUBevjOWGD18APgJuYnJwMxCcYUVJwqwE2cymYwAQ8gwAKrBzjZkol3H0Rgy64DiIyOsUigcIG8aPlaOHKGhngoITabCTABE4GHT6LxOCoW/r5KVHylsIhe5cYEnE1Aq9PjzNU7oMhWShmQL1eos7ckqfVZYHVdd7miwBp/6xfo4g4hMcmAXOV/gjKgqOsC9PCdscDq4QfAjcxXabTi33hOFeBGTmVTmICbE2CB1c0dnNa8uPgE7PrnCC5eu2nR8pDgQDStXxulSxTxMDJsLhNgAhkRMF3sVy9XjNMB8DFxKQIJSWqcuHRL7KliKf53yxbnsMBqCy3H9nU1gdUkriYkqBAfr4K3PBBFa0xkkdWxx8Lq1VhgtRoVd3RxAhS9GhmbIARWjmJ1cWfx9pgAExAEWGD1kINA+eqOnDiLf4+dhk5nLBSSssnkMtSrXgm1q1WEXMbRaR5yLNhMJmAVAdPFftWyRRHgywWsrILGnRxCgAXWzGNmgTXz7LJ7pCsJrGnFVZPtRpF1EpQB/MVGdp8HW+dngdVWYtzflQnQv/ManZ4FVld2Eu+NCTABMwEWWD3gMFy5cRu79h1BdFycRWvLlCiKZg1rIygwwANosIlMgAnYSsB0sc8pAmwlx/2zk0DKFAG0Dkew2kabBVbbeDmyt6sIrKacq6bIVS8vBcJKdEXkzVWAl4wFVkceChvWYoHVBljc1eUJkLgan6gyC6xc7MrlXcYbZAIeTYAFVjd2P+VX3b7nIG7dfWDRSsqv+kaTeihSkKvAuvExYNOYQJYJmC72aSIucpVlnDxBFgmkLXJlmo4FVtvAssBqGy9H9nYFgTXp/nyoI3eInKtxsbHC/Nyl3kPOIu2gSbgNeHlB6V/YkVh4LSsJsMBqJSjuJgkCeoMB0XGJnCZAEt7iTTIBJuDWAmuyKgb6pGgk69SAQY9kbZLwuJfCD/CWwUvuA5lfKLx83auQk1anw/7DJ3D01HkYDIZ0p1ypVKBBraqoXrk8vL28+P8CJsAEmMALCZgu9ssWK4BrdyNAkYNU6CqPKCwUwnlZ+fw4hAAVuoh4GoOIyFhQ2hulQo6ShfLgwo37Yn0WWG1zw6SZi6HVPk8Z9PHAHoIpN+cTcLbAahJXfXK9BVlQfdw6NgIGXTy8ZX4oWvNnzr3q/CPywh2wwOriDuLt2UQgORmIjI0XEaymXKw2TcCdmQATYAIOJOB+AqteA13sAxgSo4Dk9OKiRbZe3vD2zwF5cH5ApnQgfvsvde7iNfz971EkJBrF5LStYtlSaFK/Jvw5j6L94fOMTMBNCaS82DcYkhERGYN7j6JA1V2p+SjlCA7wEz9BAX4I9OM8rW56FBxqVnySGnEJSYh99qPWGMVAXx8FCubOgbxhIeJLQpOYwAKrbe75bdFqxMTGmwcN6tEeoSFBtk3CvbOFgDMF1pTiql++bsI+TcItIbJS47yr2eJyu07KAqtdcfJkLkDgSXScEFfphxqnCXABp/AWmAATsEjAfQTWZAN0MfdgiH+cJVd7B+aGPKQg4GV8A5dKi3gSiW27D+BBxBOLW84TlgOtmtZHvjy5pGIS75MJMAEXIZDRxT5Vdn0cFYun0fEwUIjBsybz9kZwoB9C6CfAH4H+Pvxh2EV86arboNv+4xLViE1IREx8EmLjE6E3PD9T3t5eCAsJFFHTOYJT5wtngTVzXl30x5+4//D5Z6bu7d5Eofx5MjcZj7IrAWcJrJbEVZNh6rhr8Jb7Q+GX36628mT2J5BZgfX46XPoPnA4PnivJ4b0625xY8vXbsLYCdMw7cdv0LRhPdGnQ5/34e/vh4XTJ9rfGBefccK0WVi4Yi1O7dsCmUxa144ujjbV9kwCKwmrph8p7Z/3ygSYgOcQcAuBlW791z69Bug09vGcXAlFWEljKgEXb0lqDfb+exSnzl3G80vR55umSNVG4TVQqVxpcDIAF3cmb48JuCiBl13sk7hKImtUXIKINlSpjZGtpkbvPf5+Pgjy9xU/AX4+8PVRinyu3DyPgE5vAP3bRZWBqXBFXKJK/J62UaQqRUXnCApAWGhghiltWGDN3BnatvtfnDx3yTy4af2aqFnl1cxNxqPsSuBl77l2XezZZC8SV7NjPZ4z+whkVmA9euI0eg0ZgVw5c2DXhqVQyNOnDHmrSz9cv3kHU8aPwetNGggjJv46G0qlEkMH9Mo+o1x05g1b/sLf/xzEz/8bbY6udNGtSnpb9GW+TCbjQleS9iJvngl4BgHJC6yUZ1X79Ib16QCs9auXNxRhxV02PytF+5w8ewl7D/0HlTq9sEy3TVatVBaN6lSHUqGw1mruxwSYABNIR8DWi33K0UpCa1yCCvFJKiGikaiWtlGkK4lofj4K+CqVItWAj5J+l4v3LRZgpXkYydcarRYqjQ5qjRZ0a79Ko0GSWivEdypYkbbJZTIR6Rzo54ugAF8R/UzPWdNYYLWGUvo+l67dxLqtu80vFMiXGz3bv5W5yXiUXQnY+p5r7eLa2KNQP90OXcI5eMkCIfMtBt8870Ibc0gUtKKcq6a0ANbOyf1cj0BWBVayaNLYL9CyWeNUxpkEWHoypcDqegR4R+5GgARWU4oAjmB1N++yPUzAvQhIWmAVkasRF7LVI4q85VwukpVu6dvy9348iYy2aHvBfHnQqmk4wnKEZisbnpwJMAHPIGCPi321VoeERBJc1UhUqZGQRILbi+86oNvCfZUK+CiMwqvxRw4fxbNHpYIj8x18BCkThFprFE3Nj89EVPqbBNSU6SIsbc/PR4kAP6XIBU75egP8fYWPM9tYYM0cORLBJ89ckmpwr46tkZ9TCWUOqB1H2eM9N+12VBEroXq8Ht7KfFAEVhIva+NPwaCJEL+zuGpHBzp5qqwKrHSre9WKFbDot0mpLPlkzHjs2L0Per2BBVYn+9iTljfeJfU8BysLrJ7kfbaVCUiPgHQFVr0Gmofn7R+5mtaHXt5Q5ivvEsWvEhKSsHP/YVy4csPiSQsKCkDT8Foo+0ox6Z1E3jETYAIuSyA7LvbJWBLrSGQlwZUqxFO0I0U9mqIfKVL/ZY2iXOk2RqVCJh4VcpmohC4e5TIonv1OAh4XRbBMkwqXaXQ6UOQxVZXX0KP4IV8YH+lv+l2n17/MJYJzSiGcRHJ/X6OgSuKql53z1bDA+lKXZNhh8ZrNuPfgkfl1ysFKuVi5OZeAvd9ztXHHkXBrApQ5GsG/QH/A61l0eLIOiffnQxP1NwKLfwl5AKeIcK7n7bN6VgXWVs2bYMtfu7F+yUyULllcbCoyKhpN2nTF6681wOYdu1MJrJS3lXKwzvp5vNmAcxevYPKMOTh97pJIORBepzpGfNAfvj7GIpg0Jjg4CNUqVcDqDVtEcd5end9F/56dhYA7c8EyrNu8A08iI1GscCH0694Rb7V4zTw/9Zk2eyE2bt2Jp5FRKFggH8JrV8eAnl2QO1dOcz+yY/ailbh55y5yh+VE+zYtxRqmzwNTZy7AolXrMHnsl5g6ayFu372HBnVq4vuvRuK1tt1Rq1olTB432jyf4PB2Nwzu2w2DencFjZ+3bDVO7t1s7vM0KhqUm3X/oWPiS+CqlStg1NCBKJg/n+hDe/9t/hKs37wD1LdEsSIY3KcbmjUKt9k++5wY156FPndExSZwigDXdhPvjgkwgWcEJCuwah9fRrL6efXb7PSol08gFLlLZ+cSL537zv2HWLFxB/Q6yxe34TWroF71SpDJrbul8qULcgcmwASYwDMC9r7YtxYsiXoU+Wq6zTxVxCQJgVpjVXlrG0XEKkmEVchA6QkolYq45Uw8Pvvxoiq1XimeS/H6s/7G6AljFVu6eHpedAEQz5heS/W68TXTONoz6cfJ9F8y/dDfRkHZ+Pez58Trz55L+1pyMgwGg4gYJZHU+GhI8Ts99+zvlK8nJ4sLPCGa6nSivy2NBOznUcWpI4rpeRK3HdlYYM087QtXb2DDtj2pJmjWsDZqVCqf+Ul5ZJYJ2Ps9N/76t9BrHiCkzC+Al1Hget6SEXvlU3grcyGw6Kgs750ncD6BrAqsv08ah0+/+QGtmjfGVyOHCoPmLF6JX+csEiJq7/dHphJYu7w3VAisc6f+KPrevf8QbXsMRGhwEFq/0RRqtRar1v+J5k0a4PsxI0UfGnPx6nWULFYUrzepDyqw1eK1hnjnzdcxfvIMLFm9Hs0ah6N8mVLYu/8QTp27iInffQ4Sf6nNXrQCP/82D326thd9rt+6g03bdmL0iA/QsG4t0Wf73/sw/Mtx4u+G9WrhwpVrWLNxqxBYhw/uK/pMnjFX2FYgf160e6sFbt97AH9fX4wZ+SHGTvwVazZtxf4tqxEY4C/6r1j7J76bMBVbV81H0cIFxfj5y1bjzP5t4nX6t7V97yG4ffc+2r75uribcMPWv8RrW1bOF4Wwxk36FcvXbELHtq1QqkRx7Np3AIeOnQRxb1C3ptX2Of+kOWYHdGcMpZuiz2tc5MoxzHkVJsAEMk9AkgKrIfEpdJG3Mm91JkbKcxaFt39YJkbaZ8jPs5YIkSFtK128COhiKDgo0D4L8SxMgAkwgTQE7H2xb0/AJpFQ+yzSUkRfpvr9WUSmVmexEKA99yLVueiCJW3ErxCiRTTws8hgBUUEO148tYYpC6zWUMq4z+I/NuPew+dRrHQeurdrBUo3xC37CJC4HRwQgIL503O293tu9LleUIbWg3/BgRYNSrw/R+RhDSk3xyaDSUSaMW8JDh87iejYWBTMnxdvtWiKvl07QKnk/P82wbRj56wKrAtnTMS+f49g+ZqN2LNpBQL8/dCifS/Url5FRJm26TbghQLrpOlzsHD5GqxbMhMlixURll29cUtEkIYEB4m/SWC9dPUG9mxanuoaJkmlQu1m76BF04aY8O3noq9arcE7PQfB388PfyyYLp4bPGIMbt66i62r52dIjtagLx6XzfpFCJvUvvnxFyF4Htu1UTxnEljn/PI96tWqnmouEnVpDhKF327VXLzW6/0RUKnUWDl3mvg7rcD6z8GjGPjxl/ju8+EiWpZadEwsIqNiUKJYYSQmJqHO6++iR6d3MPLDAeJ1ukuERNncYWGgfVhrnx2PjEtPFRmbIL48TpmD1aU3zJtjAkzAowlIUmDVPDwL6F6cu8/uXpUrocznvFunZi1dK/5xNrUcIcFo0bguihUuYHdTeUImwASYQEoC9r7YdxZdiiwx3v5ujNrMbPRnqghTijQ1R5amjzQlWy1FpNLzz6NfjVGwIsbVHP2aOuI1ZfTr8z6mSFvro3BpHRG9602iqlykUTBdeDrLL1ldlwXWrBGMjYvHvOUbRCEyU/P380Wnt1sgb4pbbbO2Co9OSYCKk06ZvVQ8Vb9WVYTXqpIqn7S933Ojz/WGMrRuxgLrvZnQRB9EaIUFVjvq1p176DrgIyQmJeH1xg0QGhKM46fPgm4NJyFuzi8/2PTekpCYKKINe3VuJ2715pZ5AvYQWOl29tfb9cQXw4egSKECGDD8C6xd9JsoPvgygXXo59/iytWbLxU/ycLlc6amMvTq9Zti/p+++SxVSoCxE6Zhw7adOLZrg+j/y8z5mLlgOV5rUBc1q1YS0aRVK1UwC7jUp26LdiJ6tWfnd81rHDh8DFN+n489G5cjT+4ws8B6Ys+f8PFRpoPeskMfFC6UX0TuPnkaiUatu+Dz4YPRvUNb0TetwEqRtxSBa5o/7YRXrt3E290H4LNhg1C9SkXzy7MWLsflqzfMzKyxL/MnRDoj6XPb05g4kR4gZQSrdCzgnTIBJuBpBCQnsCarYqB9cs0pflLkKgkv3xCnrH3j1j1s2rlP5L8Lr1EFtas5T+x1CgBelAkwAacRsPfFvtMM4YXdkgALrFl36+17D7F8/TZzmgqaUS6Xof2bzfiL3KzjTTdDfGIifp230vx8sUIF0LZlE/g+E3js/Z5rTBHwECFlpqRPEZCsQcylYZAp8yGwxNdWW0ti6K69B7Bi7lRxi7apkeA0b+lqzP/1JyF8WdueREah4Zud8PWnw9DpHc4DbC03S/3sIbCS74Z9/h2u37wtxMu4hAQsnD4RJgF0yvgxeL1JA7F82hQB3QYOF19gLp/9S4ZmpB1j6njw6An0GzoKs6d8n0ponz53MabPWYxjf28EfQGkUqvxy8wF+Gv3P7j/LAKfnqd8qZQOgK6XKtU3RpBaahQJS+c2rUCatu+MuUtEvtR9f67E5r9248dffhdRvaZCwmnHm4TRU/s2Q6FIH8V98Ohx9Bv6mcU9UZoFk4D8Mvuycj6kNDY+USVy9aeMXuV8+lLyIO+VCXgeAckJrLrImzAkRjrFU97+OSHPyQWknAKfF2UCTMBpBOx9se80Q3hhtyTAAqt93Hrs9Hns3Hc41WQUV/1K8SKoU62ixVvZ7bOy582SSmClEHgvIDgoAO3faoY8YTlh7/dcbdwJJNz6CcocjeFf4L0URa70SLw3G5rovQgo+ikUQVWtcgZFldVo2gZ1a1bDjAnfpRpDEfuPnjxF3ty5rJrL1OnxE4oO7CxyX3Z5t7VNY7lzagL2EliPnTiNnkNGiMmnfv+1yIlqjcBqbQRryrytJgusjWBNaTGlEDh64jRGj58khM81C38TL1ME69stm+GzjwZneEReJrBSGow3OvQWuWg3bd8lcrHOnPw/83yZjWCd9uM3aNqwnlVHNyP7rBos4U4k0j+OijVHr5LISo0FVgk7lbfOBDyAgOQEVs29k0CywTmu8fKGsmAV56zNqzIBJsAEnETA3hf7TjKDl3VTAiyw2s+xR0+dx65/UousptlzhoaA8r4XL1YQQYEBCArwF2kmuNlOwCywUgE7Y1080ShdR6umDWDwMnKtX8V+BVZVEaugerwO3sp8kAdWEKquLv4MDJoI+OZuC9+8naw2JOLxE1FRniJNKeL0Ze3Cpav4bf5SnL1wGZHR0SLX5FstmuDD/r1EZBrdet3wrc6ppjm6az0C/I2FhV5UCX7rzj34ZMx4kROzYvkyon9MbJyY7/1+3TGgVxfzvO16D0FocDDmTv1BPLdj9z9YvHIdrt28DY1Gg0IF8uO9Hp3Mt6Z/OOobkfJg57rFYp+m1rnfUCh9lFg0Y+LLTHfK6/YSWGnz7Xu/j9i4OGxdtUCcT2sEVlMO1g1LZ6F40cKCwY1bd5ArLKd476CWUQSrKQdry2aN8eM3xqJrGo0W7/YaBB8fH6xZMEM8R2eJUhekrEHxyej/iUJWW1bOM67Rfxgio6JFagPTWYqLT8D9hxEo80oJ0edlAqtpnrj4eFy/eSdd6oK04/cdPIJBH4/G2C8+RrvWb5jPI+VhpUjgxCQVajdvi+aN64toW1OjlBuU65YYWWufUw6XAxeNikuATqfn6FUHMuelmAATyDoBSQmsyep4aB9fzrrVWZhBkbs0vHy4oFQWEPJQJsAEJEaABVaJOczDtssCq30dfuP2PazduhtabfrCmvZdyXNno8zNlFdZJHAmdZVyOXuJZ0QrXLAAXi1fBg2rlbUrJG3sUaifbocu4ZyYVx5QAT5hLaAINlYut7bdunsPlJtyUJ9uGDqg10uHLV61Dnv2H0Kj8DoiApCKYlE04LeffYQOb7cSt5Pv3n8IJGj26tIOrzeujyoVy4tItZdVgicxtX6rDujfs4t5L39u/xuffvMDXi1XGqvm/Sr29+jxUzRuY8yf2aPjO+I5EuRIKK3yannx9/otO3Dm/CWQMEjFmTZu24XPvv0RS2b+jGqVSJQGHkQ8RtO23URUZM9OxnlcrdlTYCVx05BsgK+PjzDTGoGVoj7f6TEIYTlDRXEoisBctmajEBWpYBS1jARWem3cpF+x7I+NeKNpQ1QoWxq7/zmI46fPmcVNEinJB5SXs80bzVCsSEEhuK7bvB19u3XE8MF9xRpbd+0VPi5XuiSaN2kgCkyRWE+37m9aPkfkk7VGYF2+dhMoB6yfry/+2bJKpCgwtbTjKbr7nR4DhYhLRa5y5gjFus07oNfrzSI1zUVzNgqvjVrVKuPuvQdYv+UvtGzWCOO+/ESIsNbY52rnzp770eh0iIqJT5d7laNX7UmZ52ICTCA7CLDAaiNVFlhtBMbdmQATkDwBFlgl70K3NoAFVvu7NyEhCX//exTnLjkn5739LXKtGdMJrKbtmQRXALly5sAnKc14zQAAIABJREFU/VNHdbqKFRTx2brLe/jk/ffQr3tHsa1FK9fhhynGW7OpVShbCqvnGyu+W2rN3+2JmtUqYfxo4y3oGeVgtaYSPOXsjImNN1eYH/HV9zh59jzuP4jAvj9XiKjAtX9ux+j/TcLOdUtQIF8ei3siUazZOz0wfswItG31uhDkwlt1QKe2b5pvMzcVMfp7w1Lky5PbVVySah+ZFVhJxOw+cHgqQTmtgRSJ+mbnfkh5izuNodv9qRCUqZ0+fxE/z5iHM+cvIixnDtSvXQMjPuwvREpqlsaYxpJISXlP12/eIc4FRX72694Jbd5oap6fRNzZi1aA1qHf8+XOjdZvNEX/Xp1TRdZv3rEbcxavBEWIFsyfF9UqvyoEWCrKRm3qzAWYt2w1Tu7dnKEvKfq0ydtd8UbTRmaB2NTZ0nja809TZ2L/oWMi+rJqxfL4dOhAFC6YXwyj/LC/zVuKDVv/QlRUDEqVKIbG9WuLLwlMRSettc8lD2AWN0V8nkbHmSNXubhVFoHycCbABBxKQFICqyH+EXTRdx0KKO1i8tBC8A60/MHMqRvjxZkAE2AC2USABdZsAsvT2oUAC6x2wWhxkgePnmL3gSOgIljc7EfAGoE1R45QfDrg+e3t9ls96zPdufcALdr3ErfffzSoj5iQIhv/O2WMjKWCRCQmLZ35s3kxEk0ePX6CqOhY8dzn3/0khDMS6qhlJLBaUwmeoh0p6nHvphUiYjC8ZXt8/tFgfD/lN4z8oD/atWkJKsp1+9598y3mpo1RMaEHDx+JqEG1RiOEv5TRqR+PHocTp8+DBFWKnuvzwaciupuiWl21ZVZgdVV7eF+eQ4DE9cdRMRbFVY5e9ZxzwJYyASkTkJTAqot5AEPcA6fy9g7KD3mI8RtIbkyACTABTyDAAqsneFm6NrLAmv2+S0hS4cr127hy/RZi4uOhUmmgUqlFJBY32wlYShEgZvEyJgkokD8fKr1aDo3snCLA9p1aHmHKmUq399Nt/mlbg1Ydxa3Pk8Z9KV7auecAvps4TeRaTdmoyM+LBFZrK8E/fPQYr73dTdxeTXk5+3wwEvu3rBaiK53TKeO/Qr032qFP1/YirYGpTZu9CPOWrhK3sKdsKQXWXfv+FakLls+ZimKFC4p0BBSNaEozYC+m9pyHBVZ70uS5HEVAq9MjJj5RpAwxRa1y9Kqj6PM6TIAJ2IuApARWfewD0I8zmyw4P+iHGxNgAkzAUwiwwOopnpamnSywStNvnrzrFxW5er1hXXgrjbdR27PIlT15Jycno2bTt1G1UgXMnvJ9qqkTEhNRs2lbkUt11NCBoKJF9d5oj9fq1xW3b79SopjIfdmp34fIkyvMqgjWl1WCpw106PM+CubPJyJnKY/qgukTQAWwRv9vMqZP+A59P/wUG5fOEutTO3L8FHq/P1JE4FJBJRpH0azVGrdOFcFK0ar1W3UU+TRLlyyOz8dOwO6Ny5A3dy57IrXrXCyw2hUnT+YAAklqDWLiElIVtDKJq7Q8R686wAm8BBNgAnYhwAKrjRhZYLURGHdnAkxA8gRYYJW8C93aABZY3dq9bmmcWWAl657lXQ0OCkD7t5ohT1hOSOE9l4o//bljN5bOmoLKFZ4X45owbRbmL/sD86b9hDo1qpiLIpHI2aR+HeFPilCjXKeUp9UUwRoVHYPwlhQdOgC9u7Q3+92aSvDUeeaC5SLXZq6wHOjybmv07PwuqGJ8+BvtUbZ0ScTGxWPb6gXmeU1pBY7uWm+uME95Olt27JOugBXlbj3030mUfaUEqKjW4t8nu/S5ZIHVpd3Dm0tBgL6siUtUiRQdJKimjVxlcZWPCxNgAlIjwAKrjR5jgdVGYNydCTAByROQwsW+5CGzAZkmwAJrptHxQCcRSCWwAihWqADatmwCXx+l2JEU3nMpD2vX/sNAtlAEKEWjnjhzDkePnxbV3yePGy1soajQRm91Rr68udGp7VvIkSMEf27bhb3/HhGCq0lgNUXF5s2TG93av41O77wlCv5YUwme1rl64xbadO0v1iQhlVIFUKMCWAePnkDfbh0w4gPj69ROnD6HbgOHi0ruLZs2glanw5JV63Hp6vV0AiuNp3koiu6L4UPQrcPbTjo51i3LAqt1nLiXcwmotToRtWpKCcDiqnP9waszASZgHwIssNrIkQVWG4FxdybABCRPQAoX+5KHzAZkmgALrJlGxwOdRIBExymzl4nVG9Sqinq1qsCYfdXYpPKeS5XOp89ZjEP/nRCRnYUK5MM7b7YQ6QEoDYCp/XfqrKiqfuXaTeTPlwdt3mgmxFhfHx9MGT/G3G/d5h34+bd5eBoZhSM715kjS19WCd40wVtd+kEuk2P9kpnmOZev2YixE38VOVRTRtpSh9UbtmDuklV4/CQSJYsXweC+3THyq/H4eMh76Nq+jXkOEoAat+6Cp1HR2LNxOXLnyumkk2PdsiywWseJezmHAAXtR8XGi9zH9KUFR646xw+8KhNgAtlDgAVWG7mywGojMO7OBJiA5AlI5WJf8qDZgEwRYIE1U9h4kJMJnDhzETlzhKBoofR5/fk918nOsbA85XDV6Q1YNGOi620uzY5YYHV5F3n8BiNj4kXUeFqB1ZRrlXOuevwRYQBMQLIEJCWw6mIewBDn3CJX3kH5IQ/hIleSPfG8cSbABGwmwBf7NiPjAQ4kwAKrA2HzUg4hwO+5DsFs9SL3HjxEq459MXrEB+jwdiurxzmrIwusziLP61pLQKPTITo2dVErFletpcf9mAATcGUCkhJYDfGPoIu+61Se8tBC8A7M49Q98OJMgAkwAUcS4It9R9LmtWwlwAKrrcS4v6sT4Pdc1/HQpu27sHD5WjyIeISd6xbDz9fXdTaXwU5YYHV5F3n8Bg3JyXgaHZcqPQBHrXr8sWAATMAtCEhKYE1Wx0P7+LJTwStyl4aXT6BT98CLMwEmwAQcSYAv9h1Jm9eylQALrLYS4/6uToDfc13HQ83e7SE2M+6LT1CnRhXX2dgLdsICqyTc5PGbfBwVC5lMJtIEmH48HgoDYAJMQPIEWGC10YUssNoIjLszASYgeQJ8sS95F7q1ASywurV7PdI4fs/1SLfbzWgWWO2GkifKRgJxiSpodXoWWLORMU/NBJiA4wlISmAlPJp7J4Fkg+NJ0Ype3lAWlMa3184BxKsyASbgjgT4Yt8dveo+NrHA6j6+ZEuMBPg9l09CVgiwwJoVejzWUQQS1RokqTQiTQBHsDqKOq/DBJhAdhOQnMCqi7wJQ2JkdnOxOL+3f07IcxZzytq8KBNgAkzAWQT4Yt9Z5HldawiwwGoNJe4jJQL8nislb7neXllgdT2f8I7SE1BpdEhIUrHAyoeDCTABtyIgOYE1WRUD7ZNrTnGCIldJePmGOGVtXpQJMAEm4CwCfLHvLPK8rjUEWGC1hhL3kRIBfs+Vkrdcb68ssLqeT3hH6QmotTrEJ7LAymeDCTAB9yIgOYGV8GsenAX0Gsd6QqaEMv+rjl2TV2MCTIAJuAABvth3ASfwFjIkwAIrHw53I8Dvue7mUcfawwKrY3nzapkjoFJrkaBScwRr5vDxKCbABFyUgCQFVkPiU+gibzkUqTxnUXj7hzl0TV6MCTABJuAKBPhi3xW8wHvIiAALrHw23I0Av+e6m0cdaw8LrI7lzatljkCCSgOVmnOwZo4ej2ICTMBVCUhSYCWY2keXkayJdwhXL2UgFHlKO2QtXoQJMAEm4GoE+GLf1TzC+0lJgAVWPg/uRoDfc93No461hwVWx/Lm1TJHIDouEXqDgSNYM4ePRzEBJuCiBCQrsFKKAM3D80CyIXvRenlDma88IFNm7zo8OxNgAkzARQlk98X+/YcRmDpzAY6dOovo6BgULVwQVV4tjz7dOqBQgXwOp5KQmIiaTdvi/fd64P1+PRyyfmKSCrMXLcfOPQdw70EE8uXNjTKvlED3jm1RvTKnp3mRE1hgdcgR5UUcSCC733MdaAov5QQCLLA6ATovaTOBx1GxQlylHy8vL/HDjQkwASYgdQLSFVgBJGuToI24kK0+UOQtBy+FX7auwZMzASbABFyZQHZe7EdFx6BN1/6IT0xEy2aNERIchGs3buHg0ePImSMUuzcsEx++HdnUag1Gfv09WjZvjJZNG2X70snJyXhv2Gc4ePQEGoXXRsliRUCi84HD/yEuPgGbls8Rz1E7fvocfp+/FONHj0CusJzZvjcpLMACqxS8xHu0hUB2vufasg/uK00CLLBK02+etGuDwYCnMfEssHqS09lWJuAhBCQtsJKPklUx0D69Yf9IVi9vKMKKw8s3xEOOApvJBJgAE7BMIDsv9qfPXYzpcxZjycyfUa1SBfMG7tx7gEdPnnpE9ObRE6fRa8gIDB3YG4N6dzUzIHH18H8n0axRuPm5rTv34JMx47F5xVwUL1qYjywAFlj5GLgbgex8z3U3VmxPegIssPKpcHUCVOAqLjEJMpnMHL3KEayu7jXeHxNgAtYQkLzAKkRWimR9cg2UNsAuTaaEIldJp0WuRsbE4ubt+yjzSjEE+PnaxSSehAkwASaQWQLZebH/0Rdjsf/QURz7e2Nmtyf5ccv+2Ihxk37F6vnTUaFsqRfas3nHbhFdmzKqVfIAsmgAC6xZBMjDXY5Adr7nupyxvCG7E2CB1e5IeUI7E6DoVbp7x5QigKZngdXOkHk6JsAEnELALQRWQS7ZAPXVPfDyC80SyOSkaPi80hjwcuwtqaZNJyQkYeaSNdBoteKp5g3roHqlclmyiQczASbABLJCIDsv9sdO/BXL12xMF8Fqab96vQG/zV+C9Zt34GlUNEoUK4LBfbqlivB88jQSP/wyU6QYSEpSoXjRQmj9RlN0ebcNfHyMubRf1ker1aJq49b4aFAfvNejk3krW3ftxeyFK3Dj9h2E5QhFm5bNMaRfd8hlMtGHbvHvN3QUJo37Ems2bsPpcxeQJ3cYBvfpjjdfb5KhC7b/vQ/DvxyHYQP7YGDvLhn2M0WvmjqQGEuiLDViM3PBMqzbvANPIiNRrHAh9OveEW+1eM08H+W5XbRqHSaP/RJTZy3E7bv30KBOTfzw9aeIiY3Db/OW4t+jx/Eg4pFI1VC7ehV8OnQgcuXMYZ5j0/ZdIuL4yf/ZOwvwqK4mDH9xF4K7u7sUdysQnEL5kaKlSIECbSm00EJxihSX4hpcg3uhEIoUd5e46/+cE3bZZDdkk2yy9p2WJyvnnjPzzo3sd+fO+PqhVLEiaNeqKX78dSaWzP4NtWtUUdqSXJzScj4mPpYCqy5pci1DIJCeP3MNwT/akL4EKLCmL1+unjYCUdEx8AsMltmrrL+aNpY8mgRIwPAImI7ACiDyyhZYWNkgToisdk6AZfyH3mRHbAwQEQKLMH/ExUTBtmKnZA8RE/wj/eAf6Y9XYS8QERMBOys75HDIBXdbd7jbfvxAqtViHyZd+vcmvE9eSHBIwXy50aZJXTgwmzUlKDmXBEhARwTS88P+f7fvoXPfIbC0sETThnVQqXwZlCtVAiWLFVarvSqyPDds243O7VqiaKGCOHLyDM5f8sGimZNRp2ZV6W2/4eNw49ZdKS5mzeyBqzduyQzZ1QtnIEe2rFrNiYyMQoV6rRLcsn/4+GkMG/cLypQshoZ1auL2vYcQwmjndq0wccwwue7p85fQf8T3Usj1bNUUObNnw459h/Hw8VNsWj4PZUsV1xiR0NAwtOnRHy9evkaNKhXwWfUqKFW8KCqWKwV7OzvlMUIEXbPZCwuXr8XUCWNQsmhhFC1cQL7/26yFWLtlBxrX/0wee+L0een7jF/GoWWTeHF31sLlWLZmE3LlzI4OrZvhyfOXcLS3x/jR3+Dm7bsY+/M0tGraENmzZcajJ8+xcv1WNG1QG9N/HiePF+t1+2qobDz2efPGUqDd730CopbanzMmyfqxYmgTJx2dmvHcfe7Ir2WLxtep5SABYyeQnj9zjZ0N7U+eAAXW5Blxhv4I+AYEIyY2lvVX9RcC7kwCJJCOBExOYFVlZWHnhDgbR8DKBhBNUqw/fFCNjgBiY4GYKFhEhSIuIiQB4uQE1qu+l3H+7Vm8DnuZZGiyO+RE9ay1UMGjUorC9+L1W6zZulfeNqE6HB3s0aZpPRTImytF63EyCZAACaSVQHp/2P/78lX8PncR/rtzX2mqaHA1bvggZeanECFrNG2PL7t4YvQ3/eW8qOhodOw1GFkzZ8ayuVPka1UatpGC4i/jRiTpdnJzNAms3QeMwHtfP3itWQQH+/jSLeMmTcfuA0dw7uA2uDg7KQXWIV/1lJmtYrx8/RaNPXugT/dOGPn1V0na9PzlK/w6ayFOn7uI6JgYOc/Gxga9v+iIIf16KrNkNdVgDQsPR/XGnmjWqK5SDBWNujx7DoSjgwO2rorPclUIrIJVrWqVkz0tvp88AyI23tvXyLlTZv8ps413rF2CQgXi679+N3Eq9hw8qhRYtY1TspunYAIF1hTA4lSjIJDeP3ONAgKNTDUBCqypRscD05lAWEQkgkLClOKqIoM1nbfl8iRAAiSQYQRMWmBNLcWkBFaRqbrp4ToERPprvbSbrTu6FOwuM1u1HbcfPMaew6cgblNNPCqVK4mmdWtouxTnkQAJkECaCWTUh31x2/+N/+7gyrUb2Lh9DwKDgrF+yRyUL1MSd+8/Qtse/TF22EBUrlBW6dOS1Rtw595D7N+yUr4mhNDbd++jReP6KFOyuBQCy5cuCVtbG+Uxyc3RJLDWat5RliJQFW4PHDmJb3+cLAVMkTWqyGBdtWA6qlUqr9yvQZsvpM0imzS5ERoWjpu37uDaf3ewbfd+PHj0VAqzIiNXDE0C670Hj9Cme39Mmzg2QUmASdPnYecBb1w6slMeqxBYrxzfoyyXkNgeUT7h7TtfxMbFyWzZY6fO4cJhLzntmzETZXmEPRuWKw9T1IRVZLBqG6fkOKTkfQqsKaHFucZAIKN+5hoDC9qYcgIUWFPOjEekP4HomFi89w9UE1dZezX92XMHEiCBjCNAgVUDa00Cq8ha3flkW6oj0zZfB5RPQTar6B6948AxPH/1Vm3PzJnc4NmiIbJ4pK3ebKqd4YEkQAJmRUAfH/bv3H+Idj0GyAxOkbEqaqr2HTpWI3dHRweliPji1RtM+2MxLvzjI+uKipE7Zw6sXjgduXJkl8+Tm5NYYBUZpeVqt0C/nl0xYlAfpQ0Xr/yL/w0epczeVAisaxfPRqVypZXzmnfqhdIlimHmpO9TdN6IzNSWnfsgS+ZMylqrmgRWRe3XpXOm4LPqHzNTFyxfI+uligZi4i4IIbCuXL8F104fULPj/qMnGP3TFNy6+zGLWEwSmbkKgbVT76/l8xXzpimPFxmuvb4erWSgbZxSBCKZyRRYdUmTaxkCAX38zDUEv2mDbghQYNUNR66iOwLizkz/oBCI+quKxlZCWFX8091OXIkESIAE9EuAAqsG/okF1rSKq4otUiqyil9G5//5F6cuXJHZRKrDysoSDWpVRZXypfR7BnF3EiABkyegjw/7omlTxXqt0LZlE0z6/ltlBuu83yeiUd1aWjEXAqv3iTMY/9ss9OzaXma/Jh6a5qQ1g1VXAquwVYiXounUwa2rpelpzWBNSmDtOXgU/P0D8NN3Q2U2rhBkZy5Yhs079ioF1j7ffAdx8U/RWEvYc/TUOQz5boJSYFVksKYkTloF8xOTKLCmlSCPNzQC+viZa2gMaE/qCVBgTT07Hpk+BPyCQiD+thKNrYSoyuZW6cOZq5IACeifAAXWZATWR8EP8Ne9j7dDpjVk/Yt/naJyAWK/12/fY/v+owgIDFbbPn+enLI2q5OjQ1pN4/EkQAIkoJFAen7YFw2bRAM/UVvV2upjY0LFrec/fPs1undqC3HrfPUm7dCkfm3Mmvyj0s7HT5/Ln39ZMnvI10TmapUK5SAuQilG3VZd0LBuLWUzquTmaBJYv+g/HH7+AbIGq6Lx1A+TZ2Dnfm+cPbAVri7OyhIBKRVYT5y5gGOnz8vsWDdXlwS+te85CLVrVMHcKT/J10VjrRE/fCxLIF5T1GAVZRF+nzhGzhM+tP/fQNjZ2WHbqoXytU9lsIoSCELMHjN0gHL/0ROm4OTZv5UC64+/zpSC9ck9m5QlF0TTLLGuokSAtnHS5bcaBVZd0uRahkDg5v2niImNQ6USBeBob2sIJtEGIyEQGh6Jy7cewdrKEjXKFjESq2mmqRIQyUIBwWGIiIzUWHeV5QFMNfL0iwTMlwAFVg2xV81g/ePmdPgnU3M1m0M2VMxaET5vffA67PUnzyZRk3VYqdEpPuOio6Jx6MR5/Hvrrtqx9vZ2aNOkLgrlz5PidXkACZAACSRHIL0E1vCICHTvP1w2t8qWNbO8rT5v7ly4//CxFBwL5c+LrasWKuuFipqiG7bvlt3qRY3TZ89fYse+w2jRuB4m/zASV6//h279hqFY4YJo0qA2Mrm5SYHw5Lm/sWT2b1Ko1GaOJoFVIWyKerAig/bW3QfYd/gYOrZpoazLmtoSAT9Pm4tNXnvh5OiIiuVKoXiRQvD185diamxsnGSgaCp17eZtdOn7jfSli2drZTbv5JnzsX7rLjRvVFeWIxC1Uy//eyNBXdZPCaxfDRuHG7fu4H/dOqBwgXy48u9NrN3sJcVvRYmALTv3YcLUOeji2Qpf9/0Sj5+9kNmrIgtYIbCKcym5OCV3vqX0fQqsKSXG+YZO4P7TVxBCWRZ3Z+TPmQUOdhRZDT1mhmCfaCD0+OU7vPMPhouTPcoXzWcIZtEGMyUQExuLgMAQRMVoLgtAcdVMTwy6TQImToAC6ycEVm1LA4ypNAZCZH0T9ga/X/492VMmpaUCVBe8+/CJbIAlrgQmHhVLF0fjOtVhZf0xCyxZYziBBEiABJIhkF4Cq9g2NjYW2/ccxPHT53H73kP4+fsjT66cqFurmqx5Kmp+KoaohfrninXYuf8w/PwCULRQAdSvXR39enZTZqyev+SD9dt24r/b9+Va+fPlQd/undCySQPlOsnNEQ0GK9b/HMMH9sZXX3ZRHicE1SWrN+LR02fwcHdH25aN8fVXPZWZt4paqBuW/YHypUsoj2vZpQ/KliyuzC7VhFvYtH3PASncPn3+AjmyZkXZ0sXx9VdfIn+e3AkOEQLm7oNHkC9PbtlgSwxRUuHPlWuxY+8hvPP1Q/68udG3Rxe0ad5Ieewfi1dhxfot8DmxV82EV2/eYvKM+RA1VYXQW6NqReTOmV2KtiJDVwwhPPcf8b2coxjNGtaVQrCqwKpNnHT5TUeBVZc0uZYhEAgKDcej528MwRTaYKQEShXKDQ/Xj78/jdQNmm2kBCIio+EboLmhFeuuGmlQaTYJkIBWBIxeYI0ID8eJ48ewa4cXcrpYok/rGsicyj8o3gWEYNnucwizdEbrtu1wPavISH2VLMiZn81Uzhl5ZmSy87M75MSA4kOSnZfUhOCQUOw8eBxPX6hny2Zyc4VnywbI9uF22VRvwgNJgARI4AOB9BRYCdm4CIjb/YTA6usfgFLFiuDl67cQtVn/+nMmqlQoqxdnKLDqBTs3TWcCQmR9/d4fERFRanX403lrLm+kBKwsLeHkYIs82TNTXDXSGBq72SJrNfBDSQBFrVXVeqsUV409wrSfBEggOQJGK7D6+r7H/r17cOjgAYQEf6xNamdrjcZViqN1rVJwc9KuLmlASBj2nL2JQxf+Q1RMrGRm426DksNLJsdPvp9SgVUcM7TUKLjbZtJqfU2TRMurC1eu4dS5yxC/zFSH+AOrbo3KqFapDCxSvQMPJAESIIF4AhRYeSYoCNx78AhFChVQApm39C/8uWItTu/bDI9M7noBRYFVL9i5KQmYPQFxwUn8E3dixMTEIJOrM2x4F5nZnxfmCEDcRRMaHoHg0LAETaworprj2UCfScC8CRidwPrwwX3s2bUTp0+dlH/MJDVEcfcKRXKjcO4sKJQ7s8xqzeQSL7j6B4dBZKs+fOGL209e49qDl4j+IKwq1nMq4ITCvQprdXakRmDtWaQvCjgX0mr9T016894XXvuOwS8gUG1a3lzZ0bZZfTg7OaZ5Hy5AAiRgvgQosJpv7FU9F824Bo0aL+u+Vq1YTtZg3bJjL1o3b4TffhylN0gUWPWGnhuTgFkTUBVYhchqY2MNd2f+zW3WJ4UZOS/Of5GYFBoajrCICCmsKrJWFY8VzwUW1lw1o5ODrpKAGRMwCoFV/AD/59JF7N65AzeuX8uQcGWvnx3iX+LhbuuOERVGwNnGOVk7gqOCMdtntsYmWc1yt0T1rJ8lu4Y2E2KiY3D41Hn43LijNt3O1hatm9RB0YIsdK8NS84hARJQJ0CBlWeFgsC6LTtlDdz7D58gW5bMaNaoLgb17q5sRKYPUhRY9UGde5IACQgCigxWIbCKf27OjrCztSEcEjBqAuK8VgzxSF5MiI2T5UqiomMQERWF8PCPompS4qpCVKW4atSnA40nARJIAQGDFlhV66u+evUyBW6lfWpSAmvdXHXRtmBbrTfY9XAXTrw4oTa/Xo6GqJfjY/MRrRf8xMQHj59h1+GT8hde4lGuZFE0rVsD1jbWutiKa5AACZgRAQqsZhRsI3SVAqsRBo0mmxQBUajKPyAIfr4B8A8MQkBQMIJDQhASGiZvG46IiIRoHlizSnlUq1jGpHxPnMUqRNZsHm7M1jOpKJufM+L71i8gSHkeqwqkqqKpaqaq6mNBjOKq+Z039JgESAAwSIHVz9cXe/fsxuGD+xESEqKXOCUlsLrZuuHbCt8aVAarKiDxx+yuQyfw+Jm6IO3m6oz2LRoie9bMemHKTUmABIyTAAVW44ybuVhNgdVcIk0/DZHAkxcvsW77Aa1q/nu4u6F/j/aG6EaqbVIIrKqZrPZ2tnDVsg9EqjfmgSSQjgREluo7vwA1kTSxaJpYYKWwmo4JCi/CAAAgAElEQVRB4dIkQAJGQcCgBNaHDx5g964dOJNMfdWMIGssNViTYnHx6k0cP3sRoui46rC0sECdGpVQo1JZXl3PiBOJe5CACRCgwGoCQTRhFyiwmnBw6ZrBE3j28i3WbtujtFP1xmKLOCBOdlu1kAJs4fx50enzxgbvU0oN1JTF6mhvBxeKrClFyfkGQkA0UH7rGwDVJlUK0zSJrBRWDSRwNIMESEDvBPQusOqjvqo21G3cbVByeEltpiI1Ta6GlhoFd9tMWq2f2knvfP3htf8o3vsFqC2RO0dWtGveAC7OTqldnseRAAmYCQEKrGYSaCN1kwKrkQaOZpsMgav/3cV+79NCR4UQWKWmqjo+vFi3ekXUqlrBZPxWOKKoV5m4HqsQWIXQykECxkZA1Fp95xf4SYFVVVRN/NjY/KW9JEACJKArAnoTWGNiYnDU+zB27tiOVy8ztr6qtvCKDiwKhxwOyU5PqcCawyEn+hcfkuy6upggMliPnPkbl//9T205WxsbtGpcG8ULF9DFVlyDBEjARAlQYDXRwJqIWxRYTSSQdMOoCZy96IMTF65IH0TmagKV9cPzXp0+R47sWYzaz6SMVy0VIB6LzzmiHquzkyOcHSiymmTQTdgpIbC+9w9KILBqalTF5lUmfBLQNRIggVQR0IvAevfObcybOxsvnj9PldEZdVCmCpmQt13eZLf7ruJ3yO6YHa/DXmPa5WnJzm+brwPKe1RKdp4uJzx6+kLWZg0NC1dbtnTxwmhevyZsbNj1VJfMuRYJmAoBCqymEknT9IMCq2nGlV4ZF4HHz15g/Y6D8bqqLA0QF18Y4IO4Kh6PGdLLuJxKobWa6rEKkdXOzhZuzo4QZboyaghbKH5lFG3T2yc2Ng7vA4JgZWUlzyPFP9PzlB6RAAmQgG4JZLjA+uTxY4z7bhQiItSFPt26ppvVSgwvAVt3208uls0hGypmrQiftz5SZP3UcLd1x9BSo3VjXApXCQsLx67DJ/Hwibqw7eriBM/mDZAze9YUrsrpJEACpk6AAqupR9i4/aPAatzxo/XGT+DmnQfyIr4ccXGifXi8rvqhBquQFe1sbTGif3fjdzYZDzSJrAqxM5OrM2ysrdKVgbhzLSg0DI729rC1Sd+90tURLq5XAqIGq29AMAVWvUaBm5MACRgjgQwVWMXtMkMG9sPbt2+NhpV9DnsUG1hMZ/b2LjwAeV3y6Wy91Cx05doteJ/5GzHRMQkOF1cna1Upj8+qVcjQq+yp8YHHkAAJZBwBCqwZx5o7pZwABdaUM+MRJKArAucvX8Pxs5cSLBcHlexVIbVaWCBr5kzo262drrY16HUSi6yK2qziq62tDVwcHXQutApBLDQ8EoFBwZJNVg932NpYGzQnGme4BKKiYxAQHCpLBIh/YjAj2nDjRctIgAQMh0CGCqynT57AnFkzDMd7LS3RtlRAcss93fEU7at2RotWrZObmu7v+/oHwGvfMbz19VPbK0e2LDKb1c3VOd3t4AYkQAKGT4ACq+HHyJwtpMBqztGn7/okcPD4WVy5flvNBCdHB8TGxiAsPFL5XunihfB5k3r6NDdD905ck1WUClC8JssG2NrAycEeNtbWsLRMfekAIYQFh4YjPCIigX8ebi5yDw4SSA2BkLBIhEVEUGBNDTweQwIkYNYEMlRgnfzLBPhcvmyUwNMqsgpx1c/HDyVKlsLkKb8bBANxtVtkHVz0uaFmj6jH2qxeDZQpUcQgbKURJEAC+iNAgVV/7Llz8gQosCbPiDNIQNcENu86hAcaSk7lzJYF/+v8OcLDI7Fg9SZERUXLrZs3qIUKpYvr2gyDXU+IqWIkFloTZ7eKOaJ8goO9LWysrD40FVLPFow/DhB/u0fHxCAyKhohoWEa62OKuULkdnG0N1g+NMywCbwPCJbnrmoNVsO2mNaRAAmQgGEQyFCBtecXXRAaGmoYnqfCClEuoEDXAsnWZFVdOtI/Eo82PkL4q/ias87Ozli1dkMqdk+/Q548f4WdB4/LP9QSj2KF8qNV49ryjz8OEiAB8yRAgdU8424sXlNgNZZI0U5TICCyL1ds3IF3vgFq7pQsWhBtm9VXvu4fFIRFq7fK50P6dIOzmQl+CpFV+P8poVVVjFXM1XSuKG7RVv2auAGRYh8hjGV2451opvA9l9E+KOqvKsoDsMFVRkeA+5EACRgzgQwVWDu2+9yYWSltF9msWWpkgUMOhyT9CXsVhnfn38ms1cRj647dBsdB3Fq05/Ap3Hv0VM02ZydHtGveAHlyZjM4u2kQCZBA+hOgwJr+jLlD6glQYE09Ox5JAikhEB4ZiaVrtyEkVL1RbY3K5VC/ZmW15YTIGhocjlw5zbeJqiYBVSGEqoqvnxJXFWA/JbKqriWE8KyZXFk3MyUnOOdKAqLkRFhEpLI8AAVWnhgkQAIkoD0BCqzas1KbaeNuI7NZhdBqZW+FmPAYCGFVZK1G+UclubIhCqwKY31u3oH3yQuIjo6/pUv5Bx2A6pXLoW71ispi52lAx0NJgASMiAAFViMKlhmaSoHVDINOlzOcQFBwKJas26a85V/VgEZ1qqNq+VIZbpOxbagpo1X4kJYMVnG8avMh1Tqvrs6OsGOjK2M7TfRqrzh/3vgGyNIAbHCl11BwcxIgASMlQIFVD4EzZIFV4PAPCML2/Ufx5p2vGp1sWTzQvkVDuLu56IEctyQBEtAHAQqs+qDOPbUlQIFVW1KcRwKpI/D67Xv8tXUPYmJiEywgWjN5tmwIUU6KQ3sCiYVWxZGqr39qNVVBNXFnd1WBVbzHMgHax4UzgdDwSASHhikFVmav8qwgARIggZQRoMCaMl46mW3oAqtwUtxadPL8ZVy4fA3xZfo/DmtrazSpVx3lSxbTCQ8uQgIkYNgEKLAadnzM3ToKrOZ+BtD/9CRw//EzbN3jrcyyVOxlaWGBHh1bIVd28731XxfcNYmqSQmticVUsX/i7FXF3/Di73jxz93VCbbW1rowlWuYOIHo6Bi8DwiSmauqza00nXcmjoLukQAJkECqCWSowNq1o6fareepttxIDxTi5MatXkZj/bOXb7DjwDEEh6g3JytSIC9aN6kDezs7o/GHhpIACaScAAXWlDPjERlHgAJrxrHmTuZFwOf6bRw4flbNaWtrK/Tt2g6Z3F3NC0gGeJtcFmtyYpdqBqsQWBVZrMkdlwGucQsDJ/A+IFiK8mxuZeCBonkkQAIGTSBDBda1f63Gju3x3UTNdbRr3xE9ev7PqNyPiIzEXu/TuPPgsZrdTo4OsmNsvtw5jMonGksCJKA9AQqs2rPizIwnQIE145lzR9MncPqiD05fuKLmqIO9HQb06AB7e15cN8SzQCHQKjJYxVdHezs4O9oborlmaVN4RCRiYmPh5GA4MQkIDkVEZJSauEph3ixPUTpNAiSQBgIZKrCmwU4eagAErt+6h4MnziMqSr2BV7WKZVCvZmVYWVoagKU0gQRIQJcEKLDqkibX0jUBCqy6Jsr1zJ3AXu9TuHbrnhqGTG6u6Nfdk81ODfwESZzFKkRWVydHONjb6s1y0ZXe3tYmQUkDvRmjx42jomPw5r2ftCBLJjfY2dro0Zr4rYNCwhAaHqEUV0UGq0JYpcCq9/DQABIgASMjQIHVyAKmb3MDAoPhdeAYXr15p2ZKVo9M8GzZAB7ubvo2k/uTAAnokAAFVh3C5FI6J0CBVedIuaAZE1i7bS9EeajEI2+u7OjevqUZkzEe11WzWMVjIbDGxMTAw80FtjYZX481PDIK7/0CZNazh6uz2YqsImv19Ts/pf8iNpmFyKqHmCjO5pDwCASHhCXIXBUCqxgUV43ne56WkgAJGA4BCqyGEwujsSQ2Lg6n//bBuUtX1ZoeWFlboXHt6qhYprjR+ENDSYAEPk2AAivPEEMmQIHVkKND24yFgBDhFq3ZhsCgYDWTy5YoglaN6xiLK7QTkH+fa8pkdXd1lpmkGTVE5qpfQJAU64Q99vb28HB1yqjtDWYf8dnJNyBY9iJJ3JjM2dEhw0s4iFgEhoRBlCsQ9iSuu0px1WBOHRpCAiRgZAQosBpZwAzJ3Jev38ps1sCgEDWzCubLjTZN6sLBgOoLGRI72kICxkTg1sMXiIqORsUS+eHEunvGFDqTtzUkLAJXbj+WXbKLF8xl8v7SQRJIDwLh4RFYvHYbwsIj1JavXb0ialetkB7bcs10JpCUyOri5Agnh/StoasQ8ELDwpUlJRSZtQ729nBzdkhn7w1n+djYOPgGBsssYiFcJhZYxcUNOztbuDk7wtLCIt0Nj4iKhq9/oIwLxdV0x80NSIAEzIwABVYzC7iu3RX1WPcfO4ubdx6oLe3oYI82TeuhQF5+6NU1d65HAhlJ4NU7f7z1C4SjvS3KFskLG2urjNyee5GARgKilt21e08RGh6JrJlckSOLO0mRAAmkkICffyCWb9yB6OgYtSNF1qrIXuUwXgKqWayKcgFC0LO1tYGLo0O6/D4XzZJE0yRFR/qkBEV3Z0eTvw1dlAUQmauqLDTxUMTG1dlJ/q2VHhmk0TGxst6qaF6sEFZVvyYWf433rKflJEACJKA/AhRY9cfepHa+ff8R9nqfRqSGBliVy5VEw8+qwcqKDbBMKuh0xqwIPH31Hv5BIbC2skTe7JmRK6t7unwAMCuodDZVBMQH0Rdv/fHk9XvExMQik4sT8uTInKq1eBAJmDOBF6/fYu3WvRC3L6sOIbR0bN0YhfPnMWc8JuO7JpFVIeiJZAhHezudCK2R0TEIDglFZFT8bfCq4p0CpmJf8dXKygqZXJ1MtkGuuAjoFxgsSyMkvgVfEw8hwipilcnNRdZm1YXQKr6/Q0LDERwa9klhVRd7mcw3DR0hARIggVQSoMCaSnA8TJ1AUHAIdhw4huev3qq9KYq4e7ZoiCwezDDiuUMCxkogIDgMz9/Ei1oiizWbzBp0g4Od/joTGytL2p1yAiJT9fX7ALz2DUR0TAysra2QO5sHXJ3M51bTlFPjESSgmcCdB4/hte8oEkqrkBfDe3ZsjexZedHCVM4dxa35iYVW1eeizIqzk4P8uWr1ocmRNv4L8U4IqiIzUtQXVdx2ro3AKgRF8S9LJjedCLza2JtRc8Tvq4CgYKWwmpiLqsCauJSD6nNHe3s4SAE8/nZ+bYdYQwi8oWERCIuIUBO8FfFR/art2pxHAiRAAiSQNAEKrDw7dEpA/EI/98+/OH3hilpGhPijvUGtqqhSvpRO9+RiJEACGUcgLjYOfkEheOsbiMjoaLmxna21FLnEPxcnBzinc223jPOWO+mTQHBYhPzQLhpxiH8RkfHnm+iCLUoCiMynlHzg1Kcv3JsEDInAxas3ceTUBTWTbGys0b97B7g4OxqSubRFBwQSi6yqIp6mx85OjvKOFSG2WliIf5B/1ytEUVHHU9Tu1STUfUq801QXVrwmeja4Otob/c90wSggKDTBbfiaxFVF0y8RWtXYqGaxqrJSzLO3s4WNtTUslbGxkHVbxVxx4VFcABc180WZBjFUY5HYDsXvT/4e1cE3GJcgARIggQ8EKLDyVEgXAq/fvsf2/UcREKjejTZ/npyyNquTI7OO0gU+FyWBDCIQFBoub38LDA5TfkAQW4sPZK7ODrKJhZuTI5wd7Yz+Q1MGITXbbcSHw6DQCASGhEJkSgcGhyIm9mNunfgAKM4pDxdnODvZmy0nOk4CaSVw5PQFXPS5qbaMk6M9+vXoAHtb3pGQVsaGeryqkKcQ7DSJq4lFP1V/VMU4VYEuKVFVta6nJpFXISgqvnqIW+NtbQwV4SftEqKmb0BQko2jkqpxqomLpvioxiXxY4WYqjDwU8K36lyKq0Z5qtFoEiABAyZAgdWAg2PspkVHRePgifO4duuumiv29nZo06QuCrG+l7GHmfaTgBRXhcgaGBomb0cTtwsm+EAGwNHBDi6O9vKf6F4ssjBEdgyH+REQjTbCIiIREhaB4NBwCKFePE48RKaqOG9cHR2kuMoPguZ3rtBj3RLYefA4/rv7UG3RLB5u6NO1nbLbu2535WqGRiApoVVV1NMk4CX4vf7hdnVV0VDT7eaJf24r9hZrqWZrqgqtdnbi5769LFdgDEPcih+kUntWkSmqmjGqKmom5VNioTWpeKgyTLxW4qzUxDFh1qoxnFG0kQRIwJgJUGA15ugZie13Hz7BnsOn5O0yiUeFMsXRpHZ1WBnJH1FGgpxmkoBeCQgBLTQ8AqGhEQiLjERYeESCbESFcSLT1d7OBg52NjJrSpQaEJkr9rbWsLWxoQCr1yimfnMRf9HwMDwy/jZFcWt/uDgPIqIQHhEF0VU58RDngoO9LRxsbeHoaCdF+JTUAUy9tTySBMyDwKrNu/HqzbsEzooccdHIqvPnTcwDAr1MGH+V5maaxD2FwKd6UFIZrIkFxOQuiH2qLqxCbBUNuJwd7A22Sa4UVkPDEfGhxqkmYTWlgqaqeKpJCFeNRWKhVZvYJBcXfouQAAmQAAmkjQAF1rTx49FaEhBdRUXmxNMXr9WOyOTmCs+WDZAts4eWq3EaCZCAsREQH0TCIyIhGj+Iiy1hEdFShPvUsLS0gL2tjeykK4TX+H/WsLP58NXWBtq3fDA2YoZpr/g8HhEVL5oqv34QUcVzIaAm7kie2BMhnjvYWcssZtEgLb6mnHFkKhlmVGgVCSRNIDIyGkvWbZPd3ROPqhVKoVHt6sRn5gQ0iXqahLykxDlNwp42SD9VF1Y1u1WUFHO0F3e96P/3hLBZ1J9VNPUSvmuqbZo4s1cbHonnJBcXMV8xR1NsUhuX1NjKY0iABEiABOIJUGDlmZBhBESmxIUr13Dy3GV5W5DqEJlKdWtWRrWKZSiYZFhEuBEJ6JeAEOtEOQGR3SiEuaioaERGx8hOxOLrp26DU1guygyIhg+2NlbyqxDqxK3l8qu1FUTTFvFYiLTM3NAc79jYONmwTIjgihjIxyIOUfFfxXPxWDTRSG4IzoK5jIdNPPv4zGRbGZsUNEJObiu+TwIk8AkCoaHhWLx2q7LhjerU+rWqoEalsuRHAgkIaPN7NzGytP5uVdSBVQiGiueJGz6J3ynOTg7y94ho7JRRI76BVCxCxUXi0LD4D9DpKKxq8ksfcckovtyHBEiABEyJAAVWU4qmkfjy5r0vvPYdg19AoJrFeXNlR9tm9SG6l3KQAAmYNwHxgUYh9EVFxSAyWoiwQuiLRlSMEGKTF/tUCYqMWNsPop+4qCM+oInMk/ivH/5ZWMY/Vr6m8n6CD1QfuvMm6NILWIhLROJ/C4v4f8r3498TnwkVH0aFwBwn/osT/xJ2Ela+Jt+Pf09cpPrYkCT+sezoLL/GqXR4VjwWX2Pj31N9Py7uQ6dhwTRavpeSIeri2Vh9ELJthJBtI4VUhcDN2ropocm5JJA+BN75+mPVpl0aL4qIRqOlihVKn425KgmkgsCnGnAlFlrF8nZ2oqyQjfydbmUV/3tal0PYExUt6oVHICQ07OPvdMXvdg1fFcKr6ldd2sS1SIAESIAEDJ8ABVbDj5FJWhgTHYPDp87D58YdNf/sbG3RukkdFC2YzyR9p1MkQAK6IyBEWJFVKcTWmJgYRInnHzIto2JjIH7WiNfE15TJiLqz0dBXEgKrqCEXERkhxdyC+XLBxtJKNhixsbaEldWHx1ZWBlsLz9AZ0z4SyEgCj569wKadh9TuAhAXd7p7tkCeXNkz0hzuRQJaE/hUo6ePFxjjL0yKoZr96mhvL+9aEb+7rMQFUSvL+LviPlzs1GSEYp2YWHHhMf4CrmjCKB4rhNKkGnlpKgOQ1mxerUFxIgmQAAmQgEESoMBqkGExH6MePH6GXYdPIjxcvYN0uZJF0bRuDVjbWJsPEHpKAiSQbgSEkCgyX8UHJ/FYZoCKzFCR3Sk+qMXGytfEB63412Ljv37IIJVZNKof6BQZqIo6aHEWHzNNP2Smig93H7NR5cdBKWLKD24qH/zik2/iM1zlh0GR6RqneK6S/aohQ1bZWEMcI7JvYSm/Wll+yKIVWbpi2Q/PFdm5QjgVmajTFq5KwHzskN7pFgMuTAIkkL4Ert26h73ep9Q2EfUre3Vpgywe7ulrAFcnAR0Q+FRGq/xNKu/8UBdZFe8pTNDm1vqkmkOpNqhS3pXyIVM2cfMqCqs6CDqXIAESIAETIECB1QSCaOwuiFtvdh06gcfPXqq54ubqjPYtGiJ71szG7ibtJwESIAGDJDB1/koKrAYZGRpFAikjcP7yNRw/e0ntINFIrn/3DnB0tE/ZgpxNAnokoKnJU1LCa2JBVZOwmvi1xKJoYkFVrPmp11Tf1yMmbk0CJEACJGBABCiwGlAwzN2Uiz43cPzcJVkbUHWI7Kw61SvKZgy8QmzuZwn9JwES0DUBCqy6Jsr1SCDjCRw8fhZXrt9W21jUtB/4ZQdYW/NuoIyPCnfUFQFNYqtYO7Hgqvpa4sdJ2ZJUBmtigVX1eH4e0VVkuQ4JkAAJmBYBCqymFU+j90Y0ZfDafxTv/QLUfMmdIyvaNW8AF2cno/eTDpAACZCAoRCgwGookaAdJJA6Apt2HcLDJ8/VDs6VLSt6dm6dukV5FAkYKIHEmajJPVe4kVwGq6qgmvixpucGiodmkQAJkAAJ6JEABVY9wufWmgmIDNYjpy/g8rVbahNsbWzQqnFtFC9cgPhIgARIgAR0QIACqw4gcgkS0AMBURd66Tov+AUEqu1esmhBtG1WXw9WcUsSyFgCn6qzmtIarIktZ6ZqxsaSu5EACZCAsROgwGrsETRh+x89fSFrs4aGhat5Wbp4YTSvXxM2NjYmTICukQAJ6IJARESkaC0Fezs7XSyX4jWCQsPx5r0/wiOiZFMtDvMjIBqL2dvZIFtmd7iwDqb5nQDp4HF4ZCSWrt2GkFD1v5FqVC6H+jUrp8OuXJIEjIeANuKqwhsKqcYTV1pKAiRAAoZMgAKrIUeHtiEsLBy7Dp/UeOubq4sTPJs3QM7sWUmKBEiABDQSCAkLw/L1OxETG4P+PdrDycEhQ0kJcfXR8zcZuic3M2wCBXJno8hq2CEyeOsCgoKxbL0XoqKi1WxtXr8WKpQpbvA+0EASIAESIAESIAESMDUCFFhNLaIm6o8oF3DkzN+IiY5J4KG44ly7WgXUrFIeIkOIgwRIgAQUBES26Npte/Hi1Vv5Uq4cWdGjQ6sM/Vlx/+krhIZHIou7M/LnzAIHO1sGyAwJhEVE4vHLd3jnHwwHe1sUyZvDDCnQZV0QeP32PVZv2QNRHkB1iL+APFs2RLFC+XWxDdcgARIgARIgARIgARJIIQEKrCkExun6I+DrHwCvfcfw1tdPzYgc2bLIbFY3V2f9GcidSYAEDIrA4ZMX8M+/NxPYVKV8KTSuUz3D7Lx+76nsclypRAE42lNczTDwBriRENov33oEK0sLlCqc1wAtpEmGTuD+42fYusdb2TldYa+lpSV6dGiJXLyjx9BDSPtIgARIgARIgARMmAAFVhMOrim6FhMbi+NnL+Gizw0190Q91ub1aqJ0icKm6Dp9IgESSAGBG3ceYPehE0hc8VRmebVokGGN8q7dfSKtrl2hWAqs51RTJXDa5450rWzRfKbqIv1KJwI+12/jwPGzaqtbW1uhX/f2cHPhBeZ0Qs9lSYAESIAESIAESEArAhRYtcLESYZG4MnzV9h58DhCQsPUTBO3x7VqXBt2tswWM7S40R4SyAgCb977YvXm3YiJiYVUWD9UD1E8FIJEz06tkS2zR7qbQ4E13REb1QYUWI0qXAZj7PFz/+D8P/+q2eNgb4cBPTrA3l4/DfwMBhANIQESIAESIAESIAEDIECB1QCCQBNSRyA8IgJ7Dp/CvUdP1RZwdnJEu+YNkCdnttQtzqNIgASMkkBYeARWbtqJwKAQIC4OSFyb+cNroklen67tYJ/ONVEpsBrlaZRuRlNgTTe0JrvwXu9TuHbrnpp/mdxc0a+7J0R5AA4SIAESIAESIAESIAH9E6DAqv8Y0II0EvC5eQfeJy8gOjphN12RtFa9cjnUrV6RH0DSyJiHk4AxEBC1Ttfv2I+nz18j7kNxAAtF+uoHB1RfL5AnF7q0a5Zohm49pcCqW57GvhoFVmOPYMbav2brHjz/0KRPdef8eXKiW7vmGWsMdyMBEiABEiABEiABEvgkAQqsPEFMgoB/QBC27z+KN+981fzJlsUD7Vs0hLubi0n4SidIgAQ0ExANrURjq5SM5g1qoULp4ik5JEVzKbCmCJfJT6bAavIh1omD4oLxknVeCAwKVluvbIkiaNW4jk724SIkQAIkQAIkQAIkQAK6I0CBVXcsuZKeCcTGxuLkucu4cOWaWmMba2trNKlXHeVLstGMnsPE7Ukg3QjcvvcIXgeOpWj9Tq0bo3CB9OvoToE1ReEw+ckUWE0+xGl2MDw8AovWbEV4RKTaWrWrV0TtqhXSvAcXIAESIAESIAESIAES0D0BCqy6Z8oV9Uzg2cs32HHgGIJDQtUsKVIgL1o3qQN7OzaE0HOYuD0JZAiBqfNXJthn7JDeGbKvYhMKrBmK2+A3o8Bq8CHSq4F+/oFYvnEHoqNj1OwQWasie5WDBEiABEiABEiABEjAMAlQYDXMuNCqNBKIiIzEXu/TuPPgsdpKTo4OaNusPvLlzpHGXXg4CZCAoROgwGroETIv+yiwmle8U+Ltsxevsd5rP2JFIz6VYWFhgS5tm0LUjOYgARIgARIgARIgARIwXAIUWA03NrRMBwSu3bqLQ8fPIypRAyyxdLWKZVCvZmVYsQOvDkhzCRIwTAIUWA0zLuZqFQVWc438p/0WF4O37zuqNsnKyhI9O7ZG9qyZCY4ESIAESIAESIAESMDACVBgNfAA0by0EwgIDJZ1GV+9eae2WFaPTPBs2QAe7m5p34grkAAJGBwBCqwGFxKzNogCq1mHX6PzF6/exOO6TN8AACAASURBVJFT6s357Gxt8NUX7eHi7EhoJEACJEACJEACJEACRkCAAqsRBIkmpp2AuOXu9IUrOPfPv4hLdPudlbUVmtSujgpl0q+TeNo94AokQAKpIUCBNTXUeEx6EaDAml5kjXPdI6cv4KLPTTXjnRztMaBHJ9jaWhunY7SaBEiABEiABEiABMyQAAVWMwy6Obv88vVbmc0aGBSihqFgvtxo06QuHBzszRkRfScBkyJAgdWkwmn0zlBgNfoQ6syBrfuO4O6DJ7BItGIWDzf06doOlixfpDPWXIgESIAESIAESIAEMoIABdaMoMw9DIpAVFQU9h87i5t3HqjZ5ehgjzZN66FAXjaTMKig0RgSSCUBCqypBMfD0oUABdZ0wWp0iy5bvx3vfAMS2C1aWxXJnxedPm9sdP7QYBIgARIgARIgARIgAYACK88CsyVw+/4j7PU+jcioKDUGlcuXRMNa1SAaTHCQAAkYLwEKrPGx+3PFWjg6OMAvIBA5smVF1/at5euTps/DzgPeaN20ISaOGaYMdGhoGBq3/xLjRgzC580aaX0CiIaCsxeuwN7DRxEVFY1GdWth7PCBcHL8WEdyy859WLx6A3x9/VG2dHFM/G4YCubPq9xj3ZadWLt5B976+qJ0iaIYO2wQShYr/Ek/PmXgi1dvMOKHSXj24hXO7N+itS/pMZECa3pQNZ41IyOjsWTdNgSHhKoZXbVCKTSqXd14nKGlJEACJEACJEACJEACCQhQYOUJYdYEgoJDsOPAMTx/9VaNQ+ZMbvBs0RBZPNzNmhGdJwFjJkCBNT56C5aviRdY/QOkwPpFxza49+AR2nTvj6k/fYda1SohS2YPZahXrt+KtZu9cHDbX7C2stL6FFi0aj1Wb9iGyT+MhI2NNcb/NgtN6tfGjyOHyDUuXvkX/xs8CiMG9UG50iWwZPVGvHz9Bns2LJO3RO/a742fps7GuOGDUaxwAazbugsXLl3B3k0r4OrirNGP5IwT9hw4ehLL//gd4i4FfQ4KrPqkr9+9g4JDITJXIyLVL+rWr1UFNSqV1a+B3J0ESIAESIAESIAESCBNBCiwpgkfDzYFAqLplWh+JZpgiWZYqkMICw1qVYXIaOUgARIwPgIUWONj5n38DGztbBASGgZ3VxfUrFoJp89fwtejf8LVU/sSBDYyMgpNOnyJfj27okendikK+k9TZiNv7pzyWDHmL/tLiqaHtv0ln89dvBLnL/lgw9K58vnDx0/Rqmtf7Fi7GMUKF8TAb39EzhxZMeG7+GxaYUvNZh0w/ZdxaFinpkY/kjPwj8Wr8ODxU8z5bXxyU9P9fQqs6Y7YIDd45+uPlZt2IiYmVs0+UZaoVLFCBmk3jSIBEiABEiABEiABEtCeAAVW7VlxpokTeP32PbbvP4qAwGA1T/PnySlrszo5Opg4BbpHAqZFgAKr5ni+ePUajT2/VL4pSgb8NHqofL55x17MWbQSR3ashYN9wozPB4+e4vc/FuHazduyvErJooUx4buhKFKogMaNFq/agP3ex6WAKsakGfNlxurC6b/I5yKj9rMWnbBs7hTUqlYZPQaMQIWypTBqSD/lekJg/f7bwUmWKhj7yzQ8evwMG5f/odEGCqym9T1tbN48evYCm3YegriYqzosLSzwhWcL5MmV3dhcor0kQAIkQAIkQAIkQAIaCFBg5WlBAioEoqOicfDkOVz7754aF3t7O7RpUheF8uchMxIgASMhQIE16UAdPXUOI36YjL8Pe8Ha2lrWnBYZdi279EbrZo3Q1bM1smb5WDZArCSEWe8TZ1G9cnn4+Qdiyer1sLGxweJZv6ptFBERidbdvkLzRnUx8uuv5PtjJv6OOMRh2sSx8rmYU7F+aym41q9dA/OW/oWN23dj4YxJKFowP/7atB1/LFmNA1tWIV8ezc0Hd+47jHe+fujbo7NGZ3+Z/ofc59cfR+n9rGUGq95DkKEGXLt1D3u9T6ntKe6O6dutHTK5u2aoPdyMBEiABEiABEiABEgg/QhQYE0/tlzZiAncffgEew6fQkRkpJoXFcoUR5Pa1WFlrX1dQiNGQdNJwKgJUGBNOnyiRMCQMRPgc2KvcpLINh05/jdZDzU2Nhb58+bGrEk/oGTxIhoX8tp7CEtWb8D+zSvV3p88cz4OHTuNvRuXw8XZSb4/5LsJ8Mjkjl/GjVDOL1WzKf6YMgGN63+G8IgIKcIePn5a+X7dmtWwaNbkVJ2HQnydPn8pfhs/CmIdfQ8KrPqOQMbtf/7yNRw/e0ltQ3s7W/Tv3gGOjvqtB5xxJLgTCZAACZAACZAACZgHAQqs5hFnepkKAqLL786Dx/H0xWu1ozO5ucKzZQNkU2kKk4oteAgJkEA6E6DAmjRgTQLrF/2HIzYmFjMmfQ+RtS9qqoo6qQoB9fnLV5gwdS58rt9EaGiYXFxklooMU9UhsmOHjv0Zy+ZORY0qFZRvfTdxqnycVAarYmJAYBAeP3uOL/oNx+qFM1C5fJlUnSn7Dh/Dr7MWSkG3Ud1aqVpDlwdRYNUlTcNd6+Dxs7hy/baagaJRW//unjJjnIMESIAESIAESIAESMC0CFBgNa140hsdExAV0y5cvoaT5y/LbC7VYWVpibo1K6NaxTKw0PG+XI4ESEA3BCiwJs0xscAaHRODSvVaY86Un2RDKTHu3n+Etj36w9trLXLlyIZvxkxEVHQ0vh3cF4UK5MOeg0ewaOX6BALrm7fv5THdOrTB0P7/S2BAcjVYVSf/PG2u3H/t4tlpOhkmTZ+HsIgI/MYSAWniyIO1I7Bx50E8evpCbXKu7FnQs9Pn2i3CWSRAAiRAAiRAAiRAAkZHgAKr0YWMBuuDwJv3vvDadwx+AYFq2+fNlR1tm9WHs5OjPkzjniRAAp8gQIFVe4FVNOGp2qitzPZs2aSBPPDqjVvo9tVQnDu4DW6uLmjRubesddqxTQv5/rotO7Fms5dSYBUXovp8MwbR0dFYvXCmrOuqOuYuXom/L/+LdR9E08dPn8s1vdYsQvEiHzupv/fzR6N23fHH1AlpvrWfTa74IyIjCIhzf+k6L41/J5QsWlD+ncBBAiRAAiRAAiRAAiRgugQosJpubOmZjgnERMfg8Mnz8Ll5R21lO1tbtG5SB0UL5tPxrlyOBEggLQQosGovsIqZ30+egUtX/sVPo4dC1Ir8/Y/FcHVxwfI/4m/tH/jtjwgKCcGPI4cgMjISY37+Xb6uKBEg6rEuWL4Wi2ZOQo5sWeV74nbovLlzysfnL/mgzzffYfQ3/VGudAksXrUeT5+9xJ6NyxOIsXMWrcSJMxek8Jrc2HXgCN77+qH3Fx01TqXAmhxBvp9WAuGRkVj811aEhUeoLVWjcjnUr1k5rVvweBIgARIgARIgARIgAQMnQIHVwANE8wyPwIPHz7Dr8EmEa/ggVb5kUTSpWwPWNqyvZniRo0XmSIACa9JRP/v3Pxjy3URcPr5bOSkkNBQz5i+F9/EzECUDateogrHDByFzJnc558Gjpxg3aZq8db9g/jyoVa0yjpw8i32bVsj3Pb8ciNv3HiTYVGS+igxYxdi4fQ+WrdkIkaVapkQxTBw7HIULfLw4FRoWjgZtuuHnsSPQvFHdZE/bsb9Mk3ViNy2fp3HuyvVbceTEGaxaOAOie7s+B2uw6pN++uwdEBSMZeu9EBUVrbZB8/q1IBpjcpAACZAACZAACZAACZg+AQqsph9jepgOBEJCw7Dr0Ak8fvZSbXU3V2e0b9EQ2bNmToeduSQJkEBKCFBgTQkt05z77MUrDB79k8xyPbN/i16dpMCqV/w63/zF67dYu22fWo12UZfds2VDFCuUX+d7ckESIAESIAESIAESIAHDJECB1TDjQquMhMBFnxs4fu4SYmISNsCyFA2wqldE9UplYWHBFlhGEk6aaYIEKLCaYFBT6ZJozmWj5+7tFFhTGTwDPOz+42fYuvswRDNM1SF+//fo0BK5sseXyOAgARIgARIgARIgARIwDwIUWM0jzvQyHQm88/WH1/6jeO8XoLZL7hxZ0a55A7g4O6WjBVyaBEggKQIUWHluGBIBCqyGFI3U2+Jz/TYOHD+rtoCNjTW++sITbi7OqV+cR5IACZAACZAACZAACRglAQqsRhk2Gm1oBEQG65HTF3D52i0102xtbNCqcW0UL1zA0MymPSRg8gQosJp8iI3KQQqsRhUujcYeP/cPzv/zr9p7DvZ2GNCzI+xtbY3fSXpAAiRAAiRAAiRAAiSQYgIUWFOMjAeQQNIEHj19IWuziiYtiUfpEoXRvF5N2NjYECEJkEAGEaDAmkGguY1WBCiwaoXJYCcdOnkel//9T80+D3dX9O/RwWDtpmEkQAIkQAIkQAIkQALpT4ACa/oz5g5mRiAsLBy7Dp/EwyfP1Tx3dXGCZ/MGyMnabGZ2VtBdfRGgwKov8txXEwEKrMZ7XgQGh2LBqk1IXFW9QN5c6Nq2mfE6RstJgARIgARIgARIgAR0QoACq04wchESUCcgslyOnrmI6JiYBG+Kple1q1VAzSrlYckGWDx1SCBdCVBgTVe8XDyFBCiwphCYAU2PjY3F9D//Qlzcx7ZWFcsUR7P6tQzISppCAiRAAiRAAiRAAiSgLwIUWPVFnvuaBQFf/wB47TuGt75+av7myJZFZrO6ubIZhlmcDHRSLwQosOoFOzdNggAFVuM+Nf6+cgPHzl6UImud6pXwWdXyxu0QrScBEiABEiABEiABEtAZAQqsOkPJhUhAM4GY2FgcP3MRF6/eVJsgGmA1q1cToj4rBwmQgO4JUGDVPVOumHoCFFhTz45HkgAJkAAJkAAJkAAJkIAhE6DAasjRoW0mReDJ81fYefA4QkLD1PwqVig/WjWuDTt2HzapmNMZ/ROgwKr/GGhjwcgff0WWzB4YN2KQNtNx7eZt5M6ZHR6Z3LWabyiTKLAaSiRoBwmQAAmQAAmQAAmQAAnolgAFVt3y5Gok8EkC4RER2HnwhMYGWM5OjmjXvAHy5MxGiiRAAjoiQIFVRyDTeZnh309ClsyZ8OPIIVrt1Lj9lxjy1Zdo17KpVvMNZRIFVkOJBO0gARIgARIgARIgARIgAd0SoMCqW55cjQS0IuBz4w68T11AdHR0gvmiO3GNyuVQp3pFWFpaarUWJ5EACSRNgAKrcZwdKRZYPXvg6696wrMVBVbjiDCtJAESIAESIAESIAESIAHTJkCB1bTjS+8MmMCnGmBly+KB9i0awt3NxYA9oGkkYPgEKLDGxyggMAjjp8zC+YtXYGtri3KlS2DYgF4oXqSQfP/6f3fw66wFuHX3PnJmzyazQ1s2aSDfO3fxMr4ePQFD+vXE2s07YGEB9OjsKdf4fe4iPHj8FKWKFcGkH75F/jy55TFR0dGYOX8pdh88iqioKNSpWQ0/jf4Gbq7xP9MOHTuFleu24NHT56hVtRKCQkKQL08uZQbriTMXsGD5Gtx/+AS2tjaoWbUiJn8/Eo6ODhg0ajzE+2JUq1QeqxZMR0hoKKbOXYwz5y/B198feXLlwLABvdGkfm2DOkmZwWpQ4aAxJEACJEACJEACJEACJKAzAhRYdYaSC5FAygmIBlinzl3GhSvXEJfocBtrazSpVwPlShZN+cI8ggRIQBKgwBp/Ikyd8ycu+lzDpHEjYGFhieOnz6FRvc9QrHBBhIaGQdxyX6VCWXTv1Banz1/C8rWbsXnFfJQpWUw+7z/iezSsUxN9e3TG2YuXsWDZGjg5OuKHkYORK0d2TJo+D9myZsHyP6bK/Wb/uQJ7Dh7Bz2NHwN7eDjPmLUVmD3csmP4L3vv5o2Hb7mhc7zN08WyFoyfP4q9NXviiYxulwCpEXT//ABQrUgiPHj/Db7MXStvE/tExMWjavicG9v4C7T9vDmsrK/maEGyrV6kASwtL7Nx/GF57DuJv7x0GdTdASgTWt+/f4cdJ03Djv7uIjomGtaUVCuTPi4nfj0SRggU0focfP3UOYyf+hjy5c2LrX0t0+lMgNDQUDT/vilrVK2PWbxO0Wvve/Qf4csDwT851cnaE946Nya63dtN2LFi6CmNHfoO2LZokO9/QJwwcNgY+N27ivPduQzeV9pEACZAACZAACZAACWhBgAKrFpA4hQTSm8CnGmAVKZAXrZvUgb2dXXqbwfVJwOQIUGCND+nYn3/Hk+cv8duPo1AgX54EcRYC6tejf8K5g9tkhqgYHXoNRr1a1TG0//+UAuvJvZuQxSMTYmJiUbNZezRtUAeTfxgp5wuBdO6ilfjn2C75vF2PAejWoY0UUMW4/O8N9B7yHa6e3IuT5/7GN2N+xoXD2+XPtbi4ODTv1At1alZNsgbruEnTYWtjg5/Hxot1ydVgff7yFZq074kTuzciaxYPgzmvtRVYhZjZuksvKX67u7sid86cePP2Hd6+84W1tRU2rViI3Llzqvk1YPh3+Pf6LXnBToiWzs6OqfL9x8nT8d+t29i2dpny+ODgUDRp1xVVKpXHvGmTtFpXZBMLkVgx7t1/hKDgYBQtWBDOrk7yZZH1PGbE18mut3LdZixZuRajhg5ChzYtkp2fERO27dqPpavXYv60SShSOD4bXNvx1TejcP2/2xRYtQXGeSRAAiRAAiRAAiRg4AQosBp4gGie+RAQDbD2HD6Fe4+eqjnt5OiAts3qI1/uHOYDhJ6SgA4IUGCNh3j3/iN8M3Yinjx7AZEdX6FcKfw8ZrgUWzd57cXSvzbA22utkvjIH3+FrZ0tpowfLQXWgSN/xPUzB5Tvf9F/OGpVq4QhX/WUr134x0cKqNdOH4CVlSWqN/FEUHCIWgSFiLvf+wSWrd0E7+1rlO9/NWwcCuTLrZLBegXT5y3B/UdPZIkBMYSoJjJwxUgssIo5v8yYL7NhRearYhzbtR7Zs2bRwZmkmyW0FVgnTpmJg0dOoFb1Kpj560/Kzef+uQwbt+1CmVLFsfSP6WpG1WnWXma7itHzi04Y1OfLVBn+Rd/BePTkOc4e3qk8PjUCa+LNR4ybiPMXL2PR3KkoX7pUimwzRIF19oIl2Oy1B7N+/Qk1q1dJkT8UWFOEi5NJgARIgARIgARIwOAJUGA1+BDRQHMjcO3WXRw6fl7WMEw8qlcsg7o1K8OKDbDM7bSgv6kkQIE1IbgXr97gxq07mLNoJQrmy4P5037Gxu171ARPIbDa2dvJjFchsA4a9aMUTxWjx4ARqFmtEr7uGy/gXbzyL/43eJRSYBUC6KDe3dGuZcImVEJ83bB9tyxBkJTAGhsbi89adELndq3QrcPnyJo5M36aMguWVlZJCqwig/avTdsx9afvULZkcbzz9ZUZrMYqsDZv3x3+gYE4umcLHO3tEwSxdjNPWFhY4NSB7QleP3zsFH76dToa1a+DI8dPIlf2HNi2bmmqvnO69h6MJ88osCYHb8a8xdi2cy+mTRovM7BTMiiwpoQW55IACZAACZAACZCA4ROgwGr4MaKFZkjAPyAI2/cfxZt3vmreZ/XIBM+WDeDh7maGZOgyCaSMAAXWeF6BQcFwdXFWwlu4fC2OnT6HLSsX4NS5ixgyZmJ8iQCHeDGvY6+vUbdWNWWJgJQKrD0HjUT+fHmUgqhYU2SWZnJ3kw2qho77JckSAeI2+Hqfd8X+LSuVTbOGjfsFrq4uCQTWwX16oH3rZtLeCVPnICw8HNMmjpXPRcZu2x79jVZgFSIqEIfTB3eonfDNPL+QTcvOH0lYu7Pf0NG4duM2Nq1cgG/H/YIXr17j8M6EZQI6dO+HN+/fJxBnFZmhE8aMQPMmDSCyVx8+fqbct0SxIli5cBYUGaylSxZDQEAQRBkGIfSK539Mnwx7W9tkvzk/lcE6+89l2LH7ACIiI2S92dKlSmDutF+U62rKYO3cexCePH2O2SoZpAcOH8PshUsREBQMSwB58+TCzF8nyLq0YihqyVapWBav37xL0o8Jv87EoWMn0L93D/Tu3lnNN0X2quINOztbHN+7VT6NjIzGiHET4HPtJmJio2FnY4fWzRtj9LCBynUSC6zv3/ui/Zf9gbg47N2yRlneYdb8xdi59zAioiJkveHKFcph9pSJytrCitq0nTu0wYFDxxAYFAhrG2u0bdkco74ZkGxMOIEESIAESIAESIAESEA3BCiw6oYjVyEBnRMQWVyn//bBuX/+lTUKVYe1tTUa166GCmWK63xfLkgCpkSAAqvQa+LQuttXKFW8CLq2/xyRkZGYPHMBalSpiPGjhiAkNBSNPb9E9coV8GUXTym4Llm9AZuWz0PZUsVTlcG6dssOTJ2zCN990x+lShTF1p37cOvuA+xYuxhv3r5HY88eaNaorrTH+8QZrN6wTdnkStR4rdG0PVo3a4BeX3TE7bsPMHrCVLRp0VgpsIoasXlz5cR3Q/vLJlsiI1b8mznpB+TMnhXT5i3B8dPnlQLrsxevpCCVK0c2vZ7e2pYIqNW0raxPe3T3ZjV7233xFV6/eYMjuzbC0fFjjVUhygqB/NCODViwZBXWbt6OXt07Y0DvHso12nbri/e+vjh90Ev52tJV67Fi7UZl86ir127g+5+nwtc/ACO/GYDiRYuibKliSoE1DnHI5OaGUiWK4frN2wgMCsJnNapixuTxybJNSmCdv2Ql1m32kg3RypQsjsdPX+Dtu3cokC8vNqxYINdNLLCOmfAbTpw+hz49ukgRVAxh+4AR42BrY41qlSsiIDBQ2ujg4ICjuzfJOQqhWPjh4e6OksWLavTjt1nzsHvfYQwd2BvdOgrBO+F4Jmoaz/oDV67eQNvWLVCjcgXUr1NTTurZbxjuPnyIzJkzoWD+fLhx8xbCwiPQqV0rfDskXvRUFVjF7/u23frgna8fFs2ZoiyfoCgJIXhXrFAWdx88xNOnzxOUiFBwEf4UKpAP2bJkwT8+12RpjfGjh6FV88bJxoUTSIAESIAESIAESIAE0k6AAmvaGXIFEkhXAs9evsGOA8cQHBKqtk/BfLnRpkldOHzIOktXQ7g4CRghAQqs8UETt/Av/Wsjbty6CyHm1K5RRdY7dXN1ke9fu3kbk2fOx+17D5AzWzYM6dcTrZo2kO+du3gZA0eOlw2qFKPn4FGoVbUiBvbuLl/65+p1iKzVf0/tlzVYxR5zF6/Ctt0HEBMTI4Xa0UP6o2jhAnL+3kPHsHrjNlkTVtRyDY+IRJ6cOfD9t4Pl+0dOnsWUOX/CPyAQlcqVhquLC5ydHDFxzDD5/v4jJzB5xnwULpAPf/05U2avjvn5d5w5/w+yZM6Ejm1aYPafK3Byz0ZkyeyBQaPGw9XZGb9PHKPXs1hbgbVmk7bI5OqKfds+1qlVGN697xA8ePwEuzatQNbM8fVlRdbmz7/PRuP6dTHpx1EQzaVadeiJXDmzJWhUpY3AKtb7VA1WURPce1e8WBkdHY0GrTvLur5H96iLwYlhJyWwNmrTBRERkdi1aaUUPcXo2LM/nj1/Ba/1y6VoriqwhodHYN7iFahVvTJm/TZBuU28aHkHfy2ag2JF4ptOiQzQLTv2YszwwWjXurlSYHV2csLhnRtS5YdiQ001WOPZf4kcObLBa91yOTUwMBitOveElaUVju/bIl9TFVgHj/weV3yuYcSQAejs2VrpT8PWnWTDsoPbN8DW1lq+3q3P13j45AlO7vOSrym4VCpfFgtm/irnXLt5B/2+GSmzi5fPn6nXc56bkwAJkAAJkAAJkIC5EKDAai6Rpp9GTSAiMhJ7vU/jzoPHan6IjKU2TeuhQN5cRu0jjf9IoN83o/BFJ0+89/PHxctX8fvP3yvfPHT0JBatWINXr99gyR/TZLaX6ti59yCmzl6AVX/OQvGiRVKF9eyFS1i+ZiMePX6CrFmzoHWzxujWsZ0UzhRDCGir1m3G7oPe8PPzR/68eeRttPXr1Eqwp79/ABYsW42L//ggNDwcpYoXxZABvVGkYLzQJkZS/oomSX8uX41TZ/9GZFQUKpQtjWED+yJXzuxa+0WBVWtUJj1RCKyiodeYofq9ZVpbgfVTGaye3fvi1eu3CTJY+w4ZhRv/3cbaJXOV3ew/79IL796/x5Fdm5SZrroQWMuVKYXFc6YqzxdRduDlmzcJGmIldTIlJbDWbNwG+fLkxqZVfyoPnbNwGTZt34WJ40agWaMGSiGxXatm2LH3oMxIFnVoxVfFED77Bwbgh2+HKl97/fad/JnZ/vOW8hZ9RQZrxfKlsXDmlFT5oThIk8B68sw5jJkwRbmfYq4Qxu8/foLz3rvkSwqB9csuHbBm4zbkzqFeM1dwyZU9O/r1+kJp537vY/j7Hx9ZtkGWb1i3GUtWrsWwQX3RtUNb5bzPmrRF1qxZsWP9MpP+3qZzJEACJEACJEACJGAoBCiwGkokaAcJaEHg5u37OHD8nBSbEo/K5UuiYa1qCUQwLZbkFAMk0Hvwt+je2VPeLnrp8lXlrbcii7lNl17IkysnmjWuj1ZNG8JdpRavyOLr1HMgKpQticnjU5ep94/Pvxgy6kdUKFsKtWtWx/X/buP4qbNqdQgXLF0FUftPCKoiU+zkmfO4ffc+5kydKG/NFSM6Jga9Bg7Hsxcv4fl5C7g4OUEIwKIe6PoVC5Aze/zt2kn5O3r8ZFy4dAUd27aCk6MjtuzcIzMu1yz+A7a2NlpFjgKrVphMftLUuYtkQy4XZye9+qqtwJrSGqyfNWuHuNg4VK8S/70nhshGFhc/xIUPxS30uhBYq1Qqj3nTJin3EXVQnz17kWqBNTwyEg1adkxw27tYfNP23ZizcCn69OgqBUaFkChSOi0sLWTpC3Fr/tjhg5S2iEzY0NAwjTGuXbMqpk8arxRY0+KHYgNNAquiJurAPl/if190Utois1SvXseezX8hs4d7vMB68zZgYQFLCwvExsZh/vRJEHaJoeCS1AmbWHgeNXQQOrRpoZwuzqHMHh7YuSE+i5aDBEiABEiABEiABEggfQlQiYb//AAAIABJREFUYE1fvlydBHROICAwGF4HjuHVm3dqa2fO5AbPFg2RxSP+FksO4ySQlOB45+59/G/QCEwcNxLNGtVTc04IECv+2iDFy7y5U5fR/N34yfC5fhM71q9QNjwSWWeiDua+rX/JPUVtvybtuqF6lUrK7FpRx1N0Hi9cMD/mTP1ZztvvfRy/TJ2FKRPGKjNbX756jS69B+PzFo0xemi8MKLJXzGvfY9+MnN26MA+cp738VMYP3k6Fsz8DZXKl9EquBRYtcLESRlEQFuBtZlndwQEBeLoni1wtI9vPKYYdZq3lw9F9qYYuw8cxm8z5iXpgcj43rZmqXxf1G8VtU3PHPrYPEtxsWTsyG/QtkUTOe9TJQLSIkzqIoNVNNZavmCGvBAUFhaOnRuXK0sliAxWcQHnxL74ZlOahiKDNS1+KNZNawbrjf/uwMXZGfNnTMb/Bg6XTeD2bf1YFkJksBYrXBCrF89N0h9Nzb/EZAqsGfRNzW1IgARIgARIgARI4AMBCqw8FUjACAnExsXh/KWrsgmWeKw6RJfhBp9VReVyJY3QM5osCDx/8Up+0Bb1DUPDI5AjW3ydRUV26dzff1ZmiSqIBQQEypqF4lbaUWm4Dfr6zVsICQ1LkAm3eOUarFq3RXbIFp2yHz1+hm59B2NQ357o2a2jMmhC8Hj2/AV2bFghXxM1EkXtw+N7tyS4jXfg8DGyruDiOb/LeZr8FfUYL1+9JksKuLm5ynki+0tkgf3+yw+oW6u6VicLBVatMHFSBhHQVmAdP3kGvI+fRJ2a1TBt0o9K6xTNq0TjMEVtzV6DvsWtO/ewaeUC5M+XN4En8eUEREOs+DIBfb4eiZu37soSIuL2cjHEBQ5xvKrA2v2rb/Dg4WOcObxD+b2rC2EyKYG14eddZPO1PVtWw901/vu9U88BePr8JbavXSrLgiiExB6d2+Pr/r1w+MgJjP9thmy2tWJBfJ3RfkNH4/qNW/hl/Gg0qV9XviZ+joqSAiITXgxd+KGArGhCpcgmFa8rarDmUrnlX+zZolN3WFpa4cTeePFXkcG6ZfUi5M2TG2MniqZd5/FVz27o27ObnNPw886IjIyC1/qlShH55eu3uHn7NhrVrS3nUGDNoG9ebkMCJEACJEACJEACyRCgwMpThASMmID4oCWyWQODQtS8yJ8np6zNKhqScBg/gctXr+PrkR9rsQqPls6brqzBOufPZdi97xC2rFmibBKT2OtjJ89gs9duPHzyDFGRkRACQI+uHTRmw6oeO/KHX/Dw8VMpdIhx++49CFFn1DcD0OGDaCFeF129fa7dwMHt6+S8mfMWY9f+Qzi2J6HAOmjEWNnUSNQQTMmYMms+9h8+Bq/1y5A5UyatDqXAqhUmTsogAtoKrKGhoWjduRdCw8KQOZM78uTJiVev3+PNmzewsrbGhuXzpSgnaiHXae4J0bDpoNd6NS8U2amK2+x37T2IKbMXwMbGWl5EefnqDe49fAQLWCQQWL/9/mec+/sfFClUQGaRt2zaUCfCZFICq0KoFA0by5cphYePn+H1mzcJ6rJqEhJFwydRK1o0uqpZvQquXL2BwSPHwsLCUgrIgsv1/25JjnOm/IwaVStp7cfvsxdg575DMoNetbapKuS9B7wxecYfcHNzQZsWzTD4q57y7R79vsH9h4+RLWtmFC5YAFev3ZQ2KOrAijmqTa7Ec1ESoGmbbrL0wUGvtVIQn/3nMmzetgt2trYoW6YkwsLCcOv2PVlWwHv3Jtjb2lJgzaDvXW5DAiRAAiRAAiRAAskRoMCaHCG+TwIGTkDcrn3o5Hlc+++emqX29nZo06QuCuXPY+Be0LzkCISGhWP3gUOYs2AZhg3sg5IliqN40UKwt7PDy9dv0KXXIDg6OsDayhrWVpbylvwBfXrAQeX24vGTpsHWzhZlSpaQ2+07fERms61dOg8F8yfMfFPYc+3GLfQf9h36fNkV/f4X32hF8dpPY0agRZP4TvNiiHIAx0+fV3YT99p9ANPmLkyQcSpKW3TpNQAN63yGCeO+Tc5t5fs+125i8LfjZG3ar/v10vo4Cqxao+LEDCCgrcAqTHn99j1++GWKzC4V9YytLC2RP18e/DJupLKR1b5DRzFp2hwpgI7/briaB6J7fbP2X8i6zVv+WizfnzprPvYcPIKYmGi4ubqibu0a2L3vMCaMGYHmH76fnz9/id5ff4vA4GCUKFpUZrwK0VdkmtasVhmzp0xU7iVEzidPn+HM4Z3JEhz14yScOX8Ry+ZPR+kSCRv0zZq/GDv3HkJEVCSsLK1QplQxzJ02WYqIYihqm6pm2j5+8hRd+w5BJjdX5a31gokQbIXvllaWyJTJDcMGfoUmDerIdeL96Iqa1Sp90g9FFrH4uSd+/iU1RPOqB48fw87WHsf3bZHTIiOjMXzcePx77T9Ex8bA1sYGLZs1SVAvduCwMfC5cRPnvXcrl163eYfM/Bf1YmdMHi9fnzFvsYyPyPAVwniunDkwfdIPUmBPiot4XZSSyJY5M7ati78wxkECJEACJEACJEACJJC+BCiwpi9frk4CGUbg9v1H2Ot9WmMDrIpliqNx7eqwsrbKMHu40f/ZuwuwqpL+D+BfGrE7sbtdCxUVFUXFQDGwsHNtfdV1rbW7uxAFBSUUE0VF7C4M7MBWwkCa95lhuQIXF1DiAt95/s//3b13zjkzn3PYXb/M+U3SC0StYl25cBZq/7sRirjKyvVbscthL6pUKo9G9Q3kZlOiXmmzxg3+c7MrEcx27DEAUyaMgmmLZkoDFptq9R4yCqIKhe3mVYqwNupV/bnTJqJJowaK40SYeuCwGzz+rQ0pQuHu/YbJmojm7VvLWoN7DxyGWHm9aNYUGNarkyAkUd+116BR0NHRwra1y2WZgoQ2BqwJlWK/lBBITMCaEuPhNShAAQpQgAIUoAAFKECBpBFgwJo0jjwLBVRC4MvXb9h75CRevf2gNB6xwqdD6ybIlzuXSoyVg0i8wM8CVrGxS87s2WG1bhk0NNTlicXr+Q77DmK3qO8XbcOrwKAgvHv3Ad8DAxEUHAJRD3XUsAGw6NhOaUB/z1yA0+cuYv3y+bLOYVRTrGCdNBatjI0Un89csAzup88rVrCKL16/eYdlazfJ0gFijK/evEVR/UKw2bhaMdb4JDZZ78TWHXZxrnqL71gGrPEJ8fuUFGDAmpLavBYFKEABClCAAhSgAAVSToABa8pZ80oUSBEBUb/t4nVPeFy4JuvzRW/iFdPG9Wqido3KUEuR0fAiSSkQV8AqVpk2b2+BAZbd0d/yx2us4pV6Uet0/vS/0LhhPTkMEVTa7naC2EAqeosrYHV0OYTFK9djzPCB6GLWNkZ/8cqy2BgnvhqssecuXg0WrwgnZpMqcY4R/5sCH19/uYo2sY0Ba2LF2D85BRiwJqcuz00BClCAAhSgAAUoQIHUE2DAmnr2vDIFklVA1O9zOnwC/p+/Kl1Hv1B+tDcxQpbMesk6Bp48aQXiClgDAr6jWbuusj5q9DqBUQHrkjnTUL9uLVy7eRt/jvsbQ/r1grFRQxQuVABiNWsT085KK1gfPHoid+OuX7c25k2fpDSJZ8+90a3/MAwb0Bu9LMwV34sg9MXLV9hnZ6V0jAj7LQePks/c+uULEgVjvXMPwiMi0LdHl0QdJzqnx4C17/AJmDBiEGYtWY3Zk8ehZHF9PH/5StoU04+syxhfO3/5GoaMm4qbHgfj65ro76/cuA0r2z3o0bk9HF2OYMnsv+M9hyqNf8TEGbh07SaWzPobhga14h17YjowYE2MFvtSgAIUoAAFKEABClAg7QgwYE0794ojpUCiBUJDQuF2+iJu3H2gdKzYlbhN84YoU6Joos/LA1JH4GclAjpZDoJeJj1YrV2qeO1+2epN2L13P5x3bkWBfHlkuQBRNsDNxQ6Z9SKD9Zfer9Glz5AYAasIbPsMGyNXP1utXYasWTIrTVZsrGbc3kLu2i1WyIomjrPoNwwlihXFigX/KB1z8OhxzF64AhtXLJS1YlOqpceAtfef4zFhxGDMXrwKsyaPlTu9T569WJLOnTI+QbRnLlzB0PFTcPvMkQT1T0yny9dvYasIWDu1h4PLYSyfG7lZz381VRp/SGgoFq7cgE8+vlg6e0p8Q0/U9wxYE8XFzhSgAAUoQAEKUIACFEgzAgxY08yt4kAp8OsCD5++wIFjpxEUHPPVcHHGahXKoHkjA2hqaf76BXhkigj8LGA9ctwd/8xbiupVKqJRAwM8fPQEh93cYdamJSaOHibHdsvzHgaPnogGBrXRrLEhQkNDscf5AB4+eRojYJ2zeCUOHHGDedvWKFem5I95qanJHca1NCOfE7HT9c49e2Hc2BDlypaWtVfv3PfC0rnT5S7j0VtwcAi69hmMcmXLYP6MyEA2MU2UOhC7qG9auSgxh8m+6TFgXb9tJ9q1bAanA67o0t4U+fLmxl+zIm3mTf1fgoySM2B9+vwl3M9ehGHdWrhw9Tp6dekQ75hUafxisNvtnXHq7AVsWZm41dbxTZQBa3xC/J4CFKAABShAAQpQgAJpU4ABa9q8bxw1BRItIGp17nN1x8vX75SOzZ4tCzq2aor8eXMn+rw8IOUEbnrek5tSrVkyF39Uqxzjwm6nzmDHLge5KjVPnlxoZdwEPS3MFYGo6LzvoCtsdjvh0ydfFC+mj749u2LG3MUYOqA3OrU3leezHDRKhq5xNVcnW2TLllV+FRYWjq02djh4xA2+/v5yI62+PbqimZGh0qH2jvuwZpM1dmxciWJFiyQaTKyMDQsLwx7rDYk+Nj0GrLERrHY6YNGqjfJjscnZTY9DUFdXh+e9B5izdA3uP3yMgvnzYfiAXmjdvInsFztg3W7nhM02u7F3x3rkypkD7z98wj8LV+Di1RvQ09NDF7PW+LN/L6ipqUGsYK7euA1GDuqDg0dP4O37D2jaqD5mTBwFXR2dOO+R9+u3aGFuiQ1L56Bhvdox+qji+BmwJvpHjQdQgAIUoAAFKEABClAgQwswYM3Qt5+Tz2gCEQAu37iDU+evyIAsehOBTKO6NVD3jyoyRGGjQHoQyAgBqyjnMGnmQnm75vw9DlpaWrJkg3HHXqhVvYqshSoC1S02u7F762pUrlA2RsB6/dYd9Bs5EZuWzUWtGlXleboNHCVLSYwYaImPPr6YMmcJhvTpjt7dzCFWJFdvbIriRYtg6vjh8PXzx5Q5S/HngF7o3zPuOrn+n79g+fqt6NHZDKVLFIvxaKni+B33H8FOh31wtF6XpD8GXMGapJw8GQUoQAEKUIACFKAABVRGgAGrytwKDoQCKSfw/pMPnA+dhK//Z6WLFi6QF2Ytm8RZezPlRsgrUSBpBDJCwCqkYtcwFYHqn/+bhvOujtDTyyQxzfsMQ+P6dTFyUG9FwOpxwB4dLYeiV9cO6Nejs+wnwtB6JuY4aLcFJYrpy89EWYKrN25j0/J5ioB1yazJaGVsJL8fOn4q1NXUsGbRzF+6cao2frHitteQsTBp1giTRg35pTnFdRAD1iSj5IkoQAEKUIACFKAABSigUgIMWFXqdnAwFEg5gbDQMLidvYTrt+8rXVRbSwumxoYoV6p4yg2IV6JAMghk1IDV3vkgNm3fBTdnG4XquClzoK2jLeu0igB2yLgpqFe7Bs5evCqD0SaGBrKvKCkgQtfYrUyp4thns1ERsO5YvxQ1/y1VsXy9Fa7fvgPrNZGbbSW2xQ5YU3v8z71foeegMTBv1wqjh/RN7HR+2p8Ba5JR8kQUoAAFKEABClCAAhRQKQEGrCp1OzgYCqS8wJPn3nA55oHAwCCli1cuXxomjQ3kK8dsFEiLAhk1YLVzOoDNNvZwc9qhuG0iYNXR1cHcKeNlwDpozGQULlgABrWqy3B0r81GaGpo4PXbdzDu0AtH9myT30c1UTlElBKJKhFgs2EZ/qhaSX69csM2XL3lmWQBa2qP38HlMHY57YfjtrVJ+tgzYE1STp6MAhSgAAUoQAEKUIACKiPAgFVlbgUHQoHUE/gW8B0uR0/hufcbpUFky5oZHVo2QcH8eVNvgLwyBX5RICMFrKKW6fxpE6TU6fOXMXzijMgSAZl05Wed+vyJRvXrKEoEiIDVYdsaGaKKDajGDO0Pi45tEBoWhuqNTDFv2v/Q1qSZPDbgeyDU1dXkJlbJFbCq0vgz6iZX7qfPY9KMuShSuCActkdunBa9ObocxuKVserSRgA6Ojpo2aIpJo3+sfLZpEN3+dycPuL005/en/XZf+QY5ixeifx582DfLqtf/On/tcOGjJqIG3fu4oLb/l87AY+iAAUoQAEKUIACFMiQAgxYM+Rt56QpELfAtVv3cOLsZRmwRG+itmKDOtVRr1Y1WWeRjQJpRSCjBKwLVm7AqbMXsWTmZFQoVxrfAgLkKtS6NavL+qoicN1ovQv2W1ahSsVyMTa5Evdy8w57WO9yhKuDtazZOvKvf3D7jhcmjBqMzHqZsGbzDlSrVAGTxw77pYBV1HVdtcka3czboVTxokqPj6qNP6MGrINHT8Atz/sQGyK67bVDlix6Me6VvdN+LF+7Cblz5URR/cLyO/ELuqfPXiAkJASG9Wpj0ayp8nNjMwsEfg/CGVfnn/7jIq4+L71fwaLfMKira8DJdiPy5s6Tov+4GTBiPDzveTFgTVF1XowCFKAABShAAQqkfQEGrGn/HnIGFEhSgY8+fnA+fAKffP2VzlsgXx65mjV7tixJek2ejALJJZBRAtZHT59jxMQZePnqDW56HIKGhjpu3/XC7CWr4fXoCQrmy4fhAy1h2qKJpD5/+RqGjJuKmx4H5d8HBQXD1KIfzExbYPgAS7nR1bR5y3D20lVkz5oFdWvVwMSRg5E9W1YZpFVrZIpdm1agWuUK8vjVm7fj2k1PbF21MM5bKTaNEqtk1y+djUb16ij1UbXxi8D37bsPWDZnSpI+mqpeIqChSUeEhoXKOVt274yh/XrFmH9UwNqhXUtMGDlM8V1wcChamkeuWD13dK8sJfErAatYxWza2RJ+/v5YMHMKGtWvm6T+CTkZA9aEKLEPBShAAQpQgAIUoEBsAQasfCYoQAElgbCwcLifu4zLN+8qfSc2wDIxqodK5UpRjgIqL5BRAlaVvxFpaIAiqL519z7m/D0ehga1knTkqhywHjt5GtPmLEIzo4Y47u6BQvkLwNF2U4ICVtFp7OR/cP7SVaxdMg81qlX6pYB1xP+m4Mr1W+hi3g5jhg5IUvuEnowBa0Kl2I8CFKAABShAAQpQILoAA1Y+DxSgwE8Fnr18LWuzilVJsVvZksVgamwIHW1tClJAZQUYsKrsrVHZgYkSKRrq6lBLhnIoqhywDhz5P1kWwt5qDcb+NVNudnZsX8wyAT9bwSpuZu/Bo/Dg8VPs3WWF/HlzJzpgtbF3wuqNVihXtjSs1y1Tej7EKtnRf03Frdv3EBoeJuu+djFrgz8H9pF923TpDV8/f5w65ABNTU3F8U3bdIG6hgbc9u3C9DlLcPTkKQzq2xN9e3SJ8xmMHbB++uSDjr0GAREROLhnh6JswtLVG7Dv4DEEhQTJzeFqVq+KZfNmyNW7x9w9MG32YrRq3gTTJo5RXGfrDjtsst6JUaLesXl7lf0Z4MAoQAEKUIACFKAABRIvwIA18WY8ggIZSuD790C4HPPA0xevlOadJbMezFo2QZGC+TKUCSebdgQYsKade5URRqrKAauhSQe5IdrRvbuwZuM22Ox2Qp8eXTC4b0/FrYkKWM1MTTBxzJ/y808+fthh5wB7RxdkzpwJbi728vPElAjYvGoR+v05DhERETL4FAFo7NZz4Ag8evIMJYvro0Tx4rhy7YYsZTGoTw/062WB+cvXYd+Bwxg/cijM27WSh9+++wCDRo5HowYGWPDPZMxdugr7Dx3DyCF90a1Th3gDVlGyoH23fvjo44v1y+ehWqWK8pgV6zbDztEFObNnR43qVfDwyVO8fPkKlSuWw6aVi2Qf4SnqF7s671Rcp2ufIXjh/RonDzlAl7+czAg/8pwjBShAAQpQgAIZSIABawa62ZwqBX5H4MadB3A7fRGhoZH1+aKa2PLKoGZVNKxbQ67cYaOAKgkwYFWlu8GxqGrAeuTYSfyzYBmMjRph1pTx8PHzg6m5JQoVzAdHm82KGxcVsMZ1J8Wq0SWzp6FOrery6wQHrAGBcjXq96BAiN21xHlO7LePsQpVrCIVK1TLlysDq7VL5fkDAgPRskN3ZNIVIaYtRB/Trr1RrlRJWG9YIfv8NXMeTp46hy1rFqNS+XIJegCjr2AdNm4yrt+4jTHDB6NLhzaK45u26Sw3AnN12gVt7cjVst36/YmnL17A45Cz/Gzw6Em4efuuXBFcrKi+/Hdnw1bmKFakMOys1iZoLOxEAQpQgAIUoAAFKJB2BBiwpp17xZFSINUFfPz84XzoJD74+CqNJV+eXOjYqilyZM+a6uPkACgQJcCAlc+CKgmoasDaf/h43LnnBZuNK1C6VElJ1rZrH3z89AnHXeyhp6cnP4sKWHPnyomi+oXlZ7o6OihXphR6de2o6Cc+T2jA+u1rgHz9XqyIvel5F0fc3GFqYowp/xupuHXup8/jr3/moXH9ujBqWF/x+ZrN1vDz+4zTrk7ys/bd+uLjRx+cdnWWv/BrYdYdYWFhOL4/clVtQlpUwNqrqzl22DmicAHlWrT1jNuhUP78GNinu+KUh91O4tLVGzIALl+2NE6fv4wJU2ehdfMmmDpxDHY7H8CyNRtlSYOeXTsmZCjsQwEKUIACFKAABSiQhgQYsKahm8WhUkAVBMLCw+Fx/iouXfeUK3iiNy1NTTRvbICqFcqowlA5BgqAASsfAlUSUNWAtYGJGSLCI1C3Vg0Fl9ejJ/D19Yvxyv5/1WCN7ZyYgLVZ4waYPXUiRJ3VZu26ICw8DIccdiBHtmzytDb2jlizyTrOWyn+PXTBzUV+t3bzdlmuYNK4EahVtTLMew+CkWE9zJ8xOcGPgQxY73oBampQV1NDeHgEVi+ahVp/VJPnCAwORpPWnX56vhl/jYFJsyby+8atOyFTJh0ccbRF7yGj8eDRE5w65KRY9ZrgQbEjBShAAQpQgAIUoIDKCzBgVflbxAFSQDUFXrx6i32u7vgW8F1pgKWL66NN84ZyZRMbBVJTgAFraurz2rEFVDFg3X/kGOYuXvXTm1WoYH447tgkv0+OgDUwIBBnju5VXF9sdGW72xl1albHigUz5edRK1h7WXTCsAGWPx1rQEAAmrWzkCtIy5Uuib0HXWG1bikqlE34L/1EwHrn3gNkzZIFqxfPlsFozhzZZeAb1cQK1rKlSihKEfxsQGMn/4PzF69gz/aN6Np3GIoWKYRdW9fwB4MCFKAABShAAQpQIB0KMGBNhzeVU6JASgkEBgXhwLHTePTspdIlxeYe7U2MULRwgZQaDq9DASUBBqx8KFRJQBUD1j5Dx+L+g0eKWqHRvTr06I+3794rygQkS8D6PQhnXJ1j3KambbpAbLBo92/9UrGRlmmXXsifNw/27bJS9L105QZy5cymKGsgvujSezBevX2HnNmyQfw7KmrTrYQ+B1ErWPdYr4d+kcKYNGMuTp25gAGW3dDfsps8TdO2XRAcHALnnZuQN3ce+dmbdx9w18sLzRoZKi518859DB75Pxn2Pnj8FMMH9UOPLmYJHQr7UYACFKAABShAAQqkIQEGrGnoZnGoFFBVgVv3H+KY+wWExLEBVp0aldGoXk1ocAMsVb196XpcDFjT9e1Nc5NTtYA1PDwcDVt2QJbMmWPsdh8Fu2bTNtjYO6FfTwtZbzSlAtao65QpUQLbN0VuWNWj/3A8ef5CriatWL4s3rx5J/9ev3BB7LbeoHgWxHjFuCMiItC0UQPMnT5J8d2CZWuw79BRjBzSDxbm7eN8fqJvciU6iJIALdp1k+dzdbaRdWaXrduM3Y4u0NHWRpXKFfD9+3fc93okywq47beHrra24tzN2nbFt4AAWRPW/aAjywOkuZ9aDpgCFKAABShAAQokTIABa8Kc2IsCFIhHwM//C5wOn8D7jz5KPfPmyokOrZsgV47sdKRAigowYE1Rbl4sHgFVC1gPHT2BWQuXo3WLppg6YbTS6D9//gqTjt1RpFBB7Nm+AY4uh7F45Tp06dAGY/4c9J+zNenQHQHfA3H6SOQGVHG1/+pj2qkXfHz9sH75fFSrUkkGnaMnTsftu/cQHhaOTLq6qFShLJbMmREjtAwNDUWjVuYQ4fH2DStQtnTkpl2iTZ29GG7uHhjYuzv69bKIc0xDRk3EjTt3ccFtv+J72917sWrDVhjWq43Fs6fKzxev2oD9h44hODgYWlqaKFSwABbN+luueo3epsxagOOnzqJEcX3s3MzyAPyHBAUoQAEKUIACFEivAgxY0+ud5bwokAoC4g+0py/dwIWrt+Rqn+hNU1MTzRrWQY1K5VJhZLxkRhVgwJpR77xqzlvVAlbVVPr9UbUw64bwCMBt367fP9lvnsFh30EsWbUBo4b2/+mq2d+8BA+nAAUoQAEKUIACFFABAQasKnATOAQKpDcB7zfvsffISXz9FqA0tRJFC6Nd80bIlEk3vU2b81FBAQasKnhTMvCQGLAm/82/efsOhoyehJbNm2D6pLHJf8F4rtC1z1B4v3qNU4cdIX7RyEYBClCAAhSgAAUokD4FGLCmz/vKWVEg1QWCgoNx0O0MHjx5rjQWvUy6aNeiMYrrF0r1cXIA6VuAAWv6vr9pbXYMWJP3ji1cuRaHjpxEUEgwDu6xRq4cOZL3gv9x9qs3bmPtZmvcufcADQxqYcmcaak2Fl6YAhSgAAUoQAEKUCD5BRiwJr8xr0CBDC1w1+sxjrifR3BIiJJDrWoV0aR+bWhoqGdoI04++QQYsCafLc+ceAEGrIk3S8wRDUzMZPdh/fugR5e6GywQAAAgAElEQVTIv06tNnfpKrgcOoqC+fNhl9W6GBtfpdaYeF0KUIACFKAABShAgeQTYMCafLY8MwUo8K+A/+evcD5yEm/ff1QyyZ0zOzq0aoo8uVJvpRFvVPoVSO2A9e7jlwgLj8Af5YtDT/fHzuLpV5wz+5lAQGAwrt1/Bg11NVQspU8oClCAAhSgAAUoQAEKUCAdCTBgTUc3k1OhgCoLhEdE4MKVmzhz6QbEX0dvmhoaaNKgNmpWraDKU+DY0qBAagesj1++hQjW8uTIgmIF8yCTDkPWNPgY/faQvwcF4/mbj/jo9xWZdLVRWr/Ab5+TJ6AABShAAQpQgAIUoAAFVEeAAavq3AuOhAIZQuDNuw9yNevnL9+U5lusSEFZmzWzXqYMYcFJJr9AagesXwIC8ezV++SfKK+QZgSKF86HrHrpa5O/wyfP4Pa9x9BQV4dZKyOUKsYVumnmgeRAKUABClCAAhSgAAWSRIABa5Iw8iQUoEBiBEJCQuB66gI87z9SOkxXVwftmjdCyWJFEnNK9qVAnAKpHbCKQYmQ9d0nPwQFhSit3uZtyxgC6mpq0NXRQr7cOdJduGq92wVv3n9S3Eg9XV2MHNAtY9xYzpICFKAABShAAQpQgAL/CjBg5aNAAQqkmoDX42c46HYmzg2walQuB2PDutDQ1Ei18fHCaV9AFQJWVVekkarfIdUd37rteyBqbEdv6hpqmDC0j+oOmiOjAAUoQAEKUIACFKBAMggwYE0GVJ6SAhRIuMCXr9+w98hJvHr7QemgnNmzoUPrJsiXO1fCT8ieFIgmwPAw/seBRvEbsUdMgcDvQdhg4wBRWzZ2a92sAapWKEsyClCAAhSgAAUoQAEKZCgBBqwZ6nZzshRQTYGIiAhcvH4bHheuIzw8PMYgRU2/xvVqonaNylBTzeFzVCoswPAw/ptDo/iN2OOHwEcfP2yzd0FoWJgSi6lxQ1QpX5pcFKAABShAAQpQgAIUyHACDFgz3C3nhCmgugLvPnyC0+ETSq+cihHrF8qP9iZGyJJZT3UnwJGpnADDw/hvCY3iN2KPSAHv1+9g63wY4pdi0Zuamhq6tm+B4kUKkYoCFKAABShAAQpQgAIZUoABq4rc9m8BAbCxd8Rx97N49+EDcuXKCYNaf6Bvzy7IlyePYpQ3Pe9hyOiJPx31sAG9UbBAPkydveg/Z9bfshsGWCpvQnHl+i2M+N8UbF69CJXKl1MRnYQPY9CoCahaqQKGD+qrdNClq9cxdvI/OOK0M9Eh3cr1W3HEzR3fAr7h1CFHeW4/P3/MWrQCN255otYf1bHgn8lwcz8t7a3WLkX5ssmzike8Ut+uax/MmTYR9evWSjhOGukZGhKKY6cv4Obdh0oj1tHWRpvmDVGmRNE0MhsOM7UFGB7GfwdoFL8RewB3HzyBy9FTShQaGuro27U98uTKQSYKUIACFKAABShAAQpkWAEGrCpw64ODQzBs7GTcue+FenVqokQxfTx8/BQ3bt1BzhzZsXHVQuTPm1eO9NpNT/w5bjIaNTBAmVIllEZft2YNZM6shxMeZxXfHT52Av7+X2DRqb3is5rVq6JG1UpKx1+4fA1j/pqB9csXoFrlCj/VEUHvNlt7TPnfSOTO9aM+pqPLIdy5ex/TJo1NcdkPHz+hnUVfrF06L865zV+2Bt6v3mD14tmJGtvlazcxcsJUGNargwZ1a8GsTUt5/NrN1rCxd0IXs7aob1ATdWrWgHDZuccZo4b0R6GC+RN1nYR2PnrCA/OXrsZhRxvo6Ggn9LA01+/h0xc4cOw0goKVa/xVq1gGzRsaQFNLM83NiwNOWQGGh/F70yh+o4ze48K123A/d0WJQUdbCwO6d0TWLHyzIKM/I5w/BShAAQpQgAIUyOgCDFhV4Alw3HcQi1dtwNjhg9DZrI1iRGcvXMaEaXMwoHd39O3RRX4eFbBO/2ssWjYzStDoRWD67KU3nG02x9s/oQFr1EpNu61rUaxoEcV5F65YC48zF3Fgj3W810rqDsJxyw57HNi9Derq6jFOL+p6tuvaF717dI5hnJAx2DnsxYr1W+FiZ4W8eXIrDhk3eSZev3uLXVvWJuQ0Sdbn75kLEB4RgXnTJyXZOVX1RF+/BWCfqztevn6nNMTs2bKgY6umyJ/3xz1R1XlwXKknwPAwfnsaxW+UkXscP3MRl2/cVSIQ5VoG9TCHtjZ/0ZWRnw/OnQIUoAAFKEABClAgUoABqwo8CaMmTsddrwdwdbJVCgZFuYCo1atiqKoSsIpVlNPnLsbOLWvkituoJlaJepy9iEMO21NcduSEaShQIB8mjx2udO1bnvcwePRE7N21JYZnQga5yXontu6wg8cRJ2hp/viDpChHoKmhIVfMplQTq51bmffA/0YPS3DAnlJjS67riEp/l2/cwalzVxAWawMsEaQ3MqiBujWqQNQAZKNAbAGGh/E/EzSK3yij9tiz3w2Pnr9U2mAwT67scuUqGwUoQAEKUIACFKAABSgQKcCAVQWehM69B0NDQwNiNWh8LaUC1in/GwURot6974U8eXKhbw8LtGjaSA4vavVq1FhFrVFRc1SsXnXef0Qxhe6dzTBicD+EhITAyLSzrPnq/eYtLl6+jpDQEDSqXxdj/hwEvUy68piwsHBssrbFkWMn4ePrh4IF80OUPLDs1gl5ckeWIRD1TY+fOoPj++2RSTfyONG+fPmK1p16YcHMv+OsS7p6o5UMp7euWRKD2OvhI6zdvAN37nlBS0sL9WrXwJ+D+ijKHmzevgtbtu9SHKOtrSVrsA4cMR6e9x4oPhclG0QN1lNnL2DS9Lmw3bwKJYsXk9/7+Plh9QYrXLh8Xf4htUqVChg1uB8KFogsISDmbWVrh0Oux+Hj549iRfXRr0cXNDasp/Q4nLt4BROnzcEhhx3ImjWL/D6hvqKfvdN+HD1+Cq/evIGmlhbKlCyBYQMsUbF8WcW17j94hCWr1uPRk+fQL1wIvbqZy5IE5u1NIWr8RrVjJz2wY5cjXrx6hdy5cqJdqxbyXiVX0Pn+kw+cD52Er/9nJZfCBfLCrGUTZM2SOb4fIX6fwQQYHsZ/w2kUv1FG6yHe+thqtxcfffxjTF38wqtMcX10amOc0Ug4XwpQgAIUoAAFKEABCvynAANWFXhARN3QwgXzY92y+fGOJipgNWpYH2VLl4zRv1L5MrIOaOz2KyUCRJDYpqWxXO156NgJPH/hjS2rF8sg7vPnL9i9dz+2bLeTtVbLliqBUiWK4c3bd1i2ZhOu376DRbOmokD+fCiQLw/EqsvGrc3l6s/KlcrL0PSu10N4nL2AVs2bYNrEMXLI23c5YN2W7RDBbLkypfH8pTeOuJ3EuBGDUb9O5GZO85auxulzl+Bkuwm6OjqKqR457o5FK9bhsIMNxNhjNxFitzExRu/unRVfvXn3Hj0HjkC2LJlhYtwEX798w2G3EyiQLx+sN66Qq1NFXdf1VjYy/FyzZI6seSo2/3ry7Dmmzl4MDXV1jBs5BDmzZ0NR/cI46XEWk2cugPWG5ShbqqQMT/sOHQPv12/QukUzWVNXXEM0e6v1EJuDLFm1AaJ2rVkbExnKChex2diSOdNkTd7obe7S1Xj37gNWLPhH8XFCfQO+B2LIqImoU6s6ihfVx+cvX2HvuE8Gok62m+XqadHHvOdAGdqatmgGNXU1HHR1g3hVPyowFxc+ceoM/p61UN6XenVr4sHjp9h/6KgMWIf2t4z3Of7VDmGhYXA7ewnXb99XOoW2lhZMjQ1RrlTxXz09j0uHAgwP47+pNIrfKCP1CA4OxQabPfgWEKg07drVK6KZYd2MxMG5UoACFKAABShAAQpQIEECDFgTxJS8nVp3skSFsqWxZO40eaEHj5+g9+DRiouKAOzYvl3IrKenKBEQ14jM25li/MjBSl/9SsDar5cFBvbuLs/19v1HdOzRHz26dMCfA/vIzxJTgzUqABTh7MYVC2WoKJpYiXnhyjW4H3SQId/4KbPw4uUr7LZen2hwEWpqqKlh1tQJSseKMLTHgBGyVmrxYj/qxW6w2gEbOydYb1iBksUjd6U/6HocsxetwKJZU+SmVqJFrWI947pXMXbx+ZDRE6EuSgQsmau4ZuyA9fylqxg7+R/8NXY42rVuIfv5+3+Gr99nOZaAgO8w6dAdXTq2lat9RQsJDZWhrNg8LHqQKlYUtenSR64E7tiuleKaCfWNC/Xg0eOYvXCFDFgL5s+HU2fOY9KMebLMQtt/x+ty6KgMtqMHrGIFb3gEYtzPBcvXQmyodtxldwynRN/MBBzw5Lk3XI55IDAwSKl35fKlYdLYQK5IZqMAw8P4nwEaxW+UUXp8+RqAzTudEBQcojTlZg3rona1ihmFgvOkAAUoQAEKUIACFKBAogQYsCaKK3k6m3Xrh3z58siwSjSxQvT4qbPyr4+5e+D6TU94HHaUgVHUClax6lOs/kxI+5WAddWi2ahVo6ri9O0t+qJalUqY+fd4+dmvBKyd2pvK1ahRzc7JBSvWbpYbYuXOmRMi8Nxmu0eWDqhRtRKKFC6EqpUqIFu2rP85zaCgYLTu1BN/jRsBY6OGSn2tbHfD9bi7UgkGEco+evw0RqDr6+uH1p0tMXJIP3TrZCbP9TsBq1jpu2z1JqUNsqIG+fjpc7mKdvTQ/tI3qlnvcsDjJ89ijO2m5z0Z6u6336YomSD6RwWs8flGnVuUU3j38SNCQ0Jx885dLF+zWbHiNuqeHHTYjlw5cshDPn7yQduufWIErCYde6B+7Zroat5OMeaLV65j/dYdP51rQp7VxPT5FvAdLkdP4bn3G6XDsmXNjA4tm6Bg/ryJOSX7pkMBhofx31QaxW+UEXq8+/AJ2x0OyDcvYrd2LRqjYtmYb81kBBPOkQIUoAAFKEABClCAAgkVYMCaUKlk7Ne171BERERg9zbllZtTZy2UoaoIvERLqRqs65cvQLXKFRSzFq/Yly9TGrOm/E9+9isBa9+eXTGoTw/FOV2Pn8KMeUsU4V5gUBA2WNng1OlzePPug+wn6rPOmjIhzrqqUSc6c/6SfC3/sOMOuco3duszdCzq1qqu9Oq6CCvFpkmbVi5SHCLuQ4MWZujWqb1iRenvBKxRoXFUQB57bJev3YDYnCuupqeXCcdd7BVfrVy/Fbfv3osxXvFlVMAan+/3wEDMmLdUliCI3aJKGqzasBX2Ti44fcRZUUtVrJw1NOmgMAkNC0NDkw4//YnYtm6pLPGQUu3qrXs4efYyxLiiN3U1NTSoUx31alWD+Gu2jCnA8DD++06j+I3Se49n3q9hv++o/G+R2P8c7d6hFYoUiqwZzkYBClCAAhSgAAUoQAEKxC3AgFUFnoxxf8/Ejdt3cMTJNsYu9WJoIhyMQASs1y2TI03LAWuHti0xYdQwhbhiBevubYpNpaK+FKtSr9/yxNwlq2TdUuv1y396p0SfT598FSUWoncU5Q06dO+nqB8b/TtVWsE6/5/JaNzA4D+fxk6Wg2Bm2hI9u8bcuTkqYI3Pd/P2ndi5ey+mTRyNapUrImfOHDh36QrGTZ6pCLmtbOyxcZutDHZFwCuaqL/avL2F0grWVsZNMHrYABX4CQI++vjB+fAJfPKNuSGLGJyoAyxWs2bPFrkpGFvGEmB4GPN+X711F8c8LibqIejQqglrGydKLG11vn3/EQ66nVYatKhD3r+bGXLmyJa2JsTRUoACFKAABShAAQpQIBUEGLCmAnrsS+4/fEwGicMH9ZV1TqPa2QuXZV3S6CsTVSVgjdrkKPZqxcUrN8iNqUTN2Kjd5KMCQFFz1HrdCsUmVKIG6/nL13DqUGQN1nteD1GkUEFkzfojCBMreB88eQp7q3Vx3imxutK0c28M7d9LUeM0ekfxir6tnRP27tqqtLu9eJ3d1t4JOzauUtRmPXT0BGYtXI6Fs6agYRLUYI0KMCePG4G2rZrLoYkSEP6fv0C/SCG5qVQLMwsYGdbD7KkTFUN/6f0aenq6iuD50dNn6DVwpCwZoF+4UAyLhPqKQPnVm7eKsF6cZN9BV8xftkYRsB4+dhIzFyzD5tWL5GZeonne88LAEf+LWYN15P/g6+cvg++oVcNfvn7D2/fvUaZkiVT5qRKvtZ48dxlXbt5Vur7YAMvEqB4qlSuVKmPjRVNPgAFrTPunL17B3uVoom5I57bNUSpa/epEHczOKi1w4dptuJ+7ojRGXR1tDOphLv89xEYBClCAAhSgAAUoQAEKxC/AgDV+o2TvITY1+nPcZNy+c1++Cl+2dAl4e7+B+5nzKFy4IDYuX6CoQxoVsDZuWA/lSiuHRbX/qIbKFSKDsaj2KzVY4ysRcPf+A/QfPh4Gtf+AWZuWitWXNvZOWLNpGzqbtZE1YiuUK6N4hV1LUxOVKpRFA4M6uHP/AdxPn0PLZkaY/tdYGTR26NEfGuoaaGlshKJFCuHeg0dyB/seXToqXu9fuGItTp+7BIftG6Gjo43rt+5IO1HHNapmaPS5Dx8/BSWK6ceo/Rr1/Zu372T902zZs6F186b49jUA+12PIX+ePNi+aSXE6h3RfqdEgAj9LAeNlMFj21Yt5GpcsbFUWFgYdm/bIDeDWrxiPRz3H0IDg9r4o1oVvH79FoeOnUAzI0P8PX6kHMPWHXayLq/t5lVKz2NUwPpfvuIg6517ZI3ULmZtUa1KBVmGwXa3M3z9/BQB6/MX3rDoNwxVKpXH5LEjoa6uhlmLlsPzrleMgNXt1BmI8Lts6ZIwalgf379/h9tJD2hqaWHnljUKu2T/4YnjAs9evpa1WcUzFbuVLVkMpsaG0NHWTo2h8ZqpIMCAVRldlNS4eN0TkG+DRwCxS2jI18TV5P/V/aMymtSvnQp3jpdMbgFX93O47umldJlsWbNgUI8O0NTUTO4h8PwUoAAFKEABClCAAhRINwIMWFXkVn4LCMAOO0dZ2/T9h0/InTM7GhjURT/LrjGCw6iNjn427GEDeqOXhXmMr8Uq2OcvvbHHekO8s7187SZGTpiKTasWxQhqRZ3YimXLyDA0qolg0PWEOwoXKgSxklU0sTrz71kLcOvOPZi3M5WbRUUFgJbdOuGjjy8uXr6O4JBguUJ03PDBilfRvV+9wXY7B4jw1vv1G+TLkwcmzYxg2b2TonSCCPVEuHfiwG5k0tWFqBl6/8FjrFkyR2luYjOnVp16YuXC2fijWuU4537/wSMZCN/1eig3ETOoVQMjBveNUbJAbJK12XonPA47yUA0qg0bN1kGiSsXzlJ8dursBUyaPlcGoSWLF5Off/L1xar1W3HhynWoq6nL8HLk4H4oXKiA/F7UDhWv5otQ1d/vszyugUEtWHbrrLhe32FjYWhQB/0tLZTmkVBfEeSv2bANx056ICQsVNbUNTVpJuvgRh/vui3bsX2Xg+I6jRoY4PzFK+jcoY2iLq348ugJD9jYOeLlq9comD8fqlapiKH9eiF79tR/nfT790C4HPOAWK0Xu2XJrAezlk1QpGC+eH8e2CHtCzBgVb6Hos7mzr2H8fLVO/nlv3Gq0l/rF86P7matlFb/p/2ngjOw2+cK8cuo2K1Q/nyw7GxKIApQgAIUoAAFKEABClAgkQIMWBMJxu6JF4gKAAf17Ym+Pbok/gQ84j8FksNXlCR48vSFXElcolhRNGnTGQMsu6FfL+WAV5Vvz/U7Xjh++hJCQ0NjDFOUpDCoWRUN61SHuvqP0FyV58Kx/ZoAA9a43b4HBmHLrr2yxjLEitVYq1izZc2Mvl3bI5Ouzq/B8yiVFBBldTbZOsPX/7PS+CqUKYH2JkYqOW4OigIUoAAFKEABClCAAqouwIBV1e9QOhhfcgSA6YAlyaaQ1L6iTIAoTRFVIuHqjVsQpRbmTJ2Apo0Nk2zcKXUiHz9/OB86iQ8+vkqXzJcnFzq2aooc2bOm1HB4nRQWYMD6c/C3Hz5ih8NBhIWGxQhYxUr93l3aIl/uXCl8t3i55BQIDA7GJhtHfAtQLp8ifuFkVK9mcl6e56YABShAAQpQgAIUoEC6FmDAmq5vr2pMLqkDQNWYleqMIil9ffz80KnnIBTVL4JmjRsgKDgYjvsOIWvWzLDdtEqWUUiLLSw8HB7nr+LSdc/IspPRmqhd29zIAFXLl0mLU+OY4xFgwPrfQHcePMH+o6didGrbojEqlS3JZysdCfh/+YrNO50REhJzNb+YYkuj+qheOWbt9nQ0dU6FAhSgAAUoQAEKUIACKSLAgDVFmDP2RUJCQmBk2lluVNWza8eMjZEMs09qX1GHV2yI5fXosaxzW71KJQwf3EfWxE3r7cWrt9jn6o5vAd+VplK6uD7aNG8IXR2+Ep3W73P08TNgjf9uurqfx3XP+7JjzaoV0bxR3fgPYo80I/DuwydY7zkAUR4gelMD0KF1U4jN/9goQAEKUIACFKAABShAgd8TYMD6e348mgIUSGMCgUFBOHDsNB49e6k08sx6mWQNwqKFIzcgY0v7AhttneDj6y8nkitndgzqwV/yxL6rYoX3LufDyJRJFx1aNYV6rHqsaf8pyLgzePzcGw4H3CA2NoveRO3pnuatUSh/3oyLw5lTgAIUoAAFKEABClAgCQUYsCYhJk9FAQqkHYFb9x/imPsFhMTeAAtAnRqV0aheTWhwA6y0c0N/MtJ7j57i9MXr8tuGdWugQukSaX5OnAAFEiJww9MLR9zPKXXV1NTAwB4dkT1rloSchn0oQAEKUIACFKAABShAgQQIMGBNABK7UIAC6VPAz/8LnA6fwPuPPkoTzJsrJzq0boJcObKnz8lzVhSgQLoVOHP5Bs78+4uF6JPMpKuDwT3NoavLUijp9uZzYhSgAAUoQAEKUIACqSLAgDVV2HlRClBAVQREXUKxwvHC1VtKG2BpamqiWcM6qFGJG8Coyv3iOChAgf8WOOh2GrfvP1LqlDN7Ngzs0QGiPAAbBShAAQpQgAIUoAAFKJC0AgxYk9aTZ6MABdKogPeb99h75CS+fgtQmkGJooXRrnkjWaOSjQIUoICqCtg4HoT4Z1nsVqxIQXQza6mqw+a4KEABClCAAhSgAAUokOYFGLCm+VvICVCAAkklEBQcjINuZ/DgyXOlU+pl0kW7Fo1RXL9QUl2O56EABSiQJAJiJf76HY74/OWr0vmqlC8NU+OGSXIdnoQCFKAABShAAQpQgAIUiFuAASufDApQgAKxBO54PYar+3kEh4Qo2dSqVhFN6teGhgZfs+WDQwEKpL5AYGAQNtg44ntgkNJgDOvWgGHt6qk/SI6AAhSgAAUoQAEKUIAC6VyAAauK3OAvX79hm609Tpw+Bx8fX+TPmxctjY3Qq1snaGlqJvkoh4yeiEyZMmHZvBk/PfeqDVth5+gCj8NODJOS/A7whKou4P/5K5yPnMTb9x+Vhpo7Z3Z0aNUUeXLlUPVp/HR8XwIC8f6THwKDQhAeEZFm58GBUyChAupqatDV0UK+3DmQVS99lPvw9fuMLXZ7ERoapsQgVq2K1atsFKAABShAAQpQgAIUoEDyCzBgTX7jeK8QEhKCIWP+wt37D9CwXh0UK1oE9x88wpXrt1C/bi0snj0Vampq8Z4nMR0GjhgvA9aVC2f99LBDR0/g9PlLmDN1AjfFSAwu+6YbARE8nr9yE2cv3VAKITU1NNC0QW38UbVCmpuvCFefvVKu05jmJsIBU+AXBYoXzpfmQ9bX7z7AxuGg0j+bxH8vdGpjjFLFivyiDg+jAAUoQAEKUIACFKAABRIrwIA1sWLJ0H/vgSNYsHwtxo8cAvN2rRVXWLp6Ixz2HcSG5QtQpVL5JL1yQgLWJL0gT0aBNCzw5t0HuZr185dvSrMQm8eI2qyZ9TKlmRk+fvkWAYHByJMjC4oVzINMOtppZuwcKAV+VeB7UDCev/mIj35fkUlXG6X1C/zqqVL9OFEn2vnQCcReey5Kl1h2aoP8eXOn+hg5AApQgAIUoAAFKEABCmQkAQasKnC3R0+ajrteD3HE0SbGStGQ0FC8ffse+kWSflMdBqwqcOM5hDQlIFaau566AM/7j5TGraurg3bNG6FkGlkx5vnoJSIiIvBH+eLQ02W4mqYeRA72twTELxau3X8GDXU1VCyl/1vnSq2DL9+8i+OnLypdXktLE4N6mCNrFr3UGhqvSwEKUIACFKAABShAgQwrwIBVBW59J8tB0NbUws6ta+IdjdfDR1i7eQfu3POClpYW6tWugT8H9UHuXLkUx/r6+mH1Zmucv3gVQcFBqFiuDIb2t0TF8mUVfWIHrI+fPseQMZPQrLEhJo35U/bbaGUD2z3OOHXIUXGcj58fVm+wwvlL1yACJ7GyVly/dIniij5tOvdGwQJ5sWnV4njnww4USGsCXo+f4aDbmTg3wKpRpTyMG9SBhqaGSk/r9sMXcnyG1X/8M0GlB8zBUSAJBc7ceCDPVqVM0SQ8a8qcyv38VVy4ekvpYpn1dDGwpzl0tfkLk5S5E7wKBShAAQpQgAIUoAAFYgowYFWBJ6KdRV8ULpgf65bN/8/RvHn3Hj0HjkC2LJlhYtwEX798w2G3EyiQLx+sN66AqAkZHh6OvsPG4sXLV2jVogmyZ8uKI8dPwd/vM6w3LId+4cjVsNED1s+fv6Dvn2ORN3curFo0Wwa3oq3dbI2de5xxxnWv/PuwsHD0HToGHz75oEMbE+jp6eGAqxt8fP2wa8tqRcjbvd+fyJ8/739uoKUC7BwCBX5ZQGxKt/fISbx6+0HpHDmzZ0OH1k2QL/ePX3r88oWS6UAGrMkEy9OmCYG0GrDuc3XHvYdPlYzz5MqOfhZmrJWeJp4+DpICFKAABShAAQpQIL0KMGBVgTvbyrwXKpYvgyVzpv3naDZY7YCNnROsN6xAyeKRK28Ouh7H7EUrsGjWFBjWq4PL125g5IRpchVqe1MT2ef5C2/0GjQSnczaYOSQfvKzqIB12bx/MOav6bs1AgEAACAASURBVHjp/Qpb1i5Frhw/dkWPHbBeuHwNY/6aITfdamBQW57nzdt3sOg3DP16WqB3984qoMkhUCBlBMQr9hev34bHhevyFxvRm4a6OhrXr4Xa1SshabenS5q5MWBNGkeeJW0KpMWA1Xq3C968/6QEXrJYYXRp2yJt3giOmgIUoAAFKEABClCAAulIgAGrCtzMtl37oEihAvGuYJ08cwEePX6K3dbrFaMW5QBad7aUwWm3TmZyU6wlqzbAxc4KefP82ORCrCotXLigDGKjB6wlSxSDvaMLJo8djratY/4hLXbAumfvAYiNt9YunYdMujqKMfw1cz7q/FEdf40drgKaHAIFUlbg3YdPcDp8Av6fvypdWL9QfrQ3MUKWzKpVE5EBa8o+I7yaagmkpYA1NDQU63c44uu3ACXEGpXLwcSovmrhcjQUoAAFKEABClCAAhTIoAIMWFXgxie0BuuQ0RMRFh6OTSsXKUYtVtE1aGGGbp3aY8TgfrJuqpXtbngcdlS86i86Dxs3Gd+/B8Jq7VJFwPr0uTe+BQTIVatZs2XBjo0roaWpqTh37IBVrKDdZrsnTjGxejYqvFUBUg6BAikqEBoSimMeF3Dz3kOl6+poa6NN84YoU0J16j0yYE3Rx4MXUzGBtBKwBgQEYqOtIwKDgpUEjerXgsEfVVRMlsOhAAUoQAEKUIACFKBAxhVgwKoC9370pOm49+ARDjvsiFFDLTQsDO/efUDhQgXkKJN6BavnvQfo18sC1SpXwKiJ02VA272z2U8D1qgVrEf37kLWLJlVQI5DoIBqCTx8+gIHjp1GULByIFKtYhk0b2gATa0fv8RIrdEzYE0teV5XFQTSQsD60ccP2+xdIP47IHZr16IxKpYtqQqUHAMFKEABClCAAhSgAAUo8K8AA1YVeBScXA5j0cp1MeqmimEtX7cZe5wPYP2y+ahSqTzWb90BW3sn7Ni4CsWLFZEjP3T0BGYtXI6Fs6agYb06uHT1ugxLo7/y/9L7NXoMHAHz9q0xakh/eZyowRoUHArr9cugpqaGSTPmyfqtu7etU2xWFXsF68Ur1yHC4PEjh8C8XWuF3O0791G+XOkYq19VgJVDoECqCIhXecVmNC9fv1O6fvZsWdCxVVPkz/ujfEdqDJIBa2qo85qqIqDqAav363ewdT4M8YZK9Cb+Xd21fQsULxK5WSUbBShAAQpQgAIUoAAFKKA6AgxYVeBeBAeHYPDoifB6+BiNDeuheNHC8Hr4BOcvXUWdmjWwfP4MGYKKDaV6DhyBbNmzoXXzpvj2NQD7XY8hf5482L5pJTQ1NBAWFo6+Q8fA+/UbtGlpjGzZsuLwsRPw8fHD9g0roP/vH8yiNrlauXCWFHj95h269R+GZo0NMW3iGPlZ7IBVnLv3kFF4+eo1TIyboLh+Edy554UTHmcxdcJotG7RVB7Xa+BI5MuXJ95Nu1SAnkOgQLIIiFjk8nVPnDp/VZb1iN7U1dXRyKAG6taoIn+uU6MxYE0NdV5TVQRUOWC9++AJXI6eUqIS/37v07Ud8uT6sRGlqnhyHBSgAAUoQAEKUIACFKAAwIBVRZ6CL1++YouNHTzOnMcnXz+5QVVLYyP07tY5Ri3V+w8eYc2mbbjr9VB+blCrBkYM7qtYdSqm4+Pnh9UbrHDu0lWEBAejfNkyGDbQEpXKl1PMVtRzzZQpE5bNm6H4bMt2O2zevhNb1yxBhXJlZD1X2z3OOHXIUdFHnnv9Vly4cgOhYaEoX6YU2pmawLixoaKPaSdLFCyQH5tX/6gVqyLMHAYFUlTg/ScfOB86CV//z0rXLVwgL8xaNkmVchsMWFP0MeDFVExAVQPWC9duw/3cFSUtHW0tDO7ZCXp6uiomyeFQgAIUoAAFKEABClCAAlECDFj5LFCAAhRIRoGw0DC4nbmI655eSlfR1tKCqbEhypUqnowjUD41A9YU5ebFVExAFQPW42cu4vKNu0pSWTLrYVAPc2hrp37tZhW7jRwOBShAAQpQgAIUoAAFVEqAAatK3Q4OhgIUSK8CT557w+WYBwIDg5SmWKVCabRoZBBjtXpyOjBgTU5dnlvVBVQtYN2z3w2Pnr9E7IIhBfLlQZ8ubVWdk+OjAAUoQAEKUIACFKAABcASAXwIKEABCqSYwLeA77K+4nPvN0rXzJY1Mzq0bIKC+fMm+3gYsCY7MS+gwgKqErCGh4djq91efPTxV9KqUKYE2psYqbAih0YBClCAAhSgAAUoQAEKRBfgClY+DxSgAAVSWODqrXs4efYyQsPCYlxZXU0NhnWqw6BWNYi/Tq7GgDW5ZHnetCCgCgFrcHAoNtjswbeAQCWy2tUroplh3bRAyTFSgAIUoAAFKEABClCAAv8KMGDlo0ABClAgFQQ++vjB+fAJfPJVXr0mXg0Wq1mzZ8uSLCNjwJosrDxpGhFI7YD1y9cAbN7phKDgECWxZg3rona1imlEksOkAAUoQAEKUIACFKAABaIEGLDyWaAABSiQSgJhYeE4ee4yrtxU3txGbIDV0qgeKpYrleSjY8Ca5KQ8YRoSSM2A9d2HT9jucADiZz9269i6KcqWLJaGJDlUClCAAhSgAAUoQAEKUIABK58BClCAAioi8Ozla1mbNeC78uvCInAxNTaEjrZ2ko2WAWuSUfJEaVAgtQLWZ96vYb/vKCIiImKoiXIg3Tu0QpFC+dOgJodMAQpQgAIUoAAFKEABCggBrmDlc0ABClBABQS+fw+EyzEPPH3xSmk0WTLrwaxlExQpmC9JRsqANUkYeZI0KpAaAevt+49w0O20kpimpgb6W5ghZ45saVSTw6YABShAAQpQgAIUoAAFGLDyGaAABSigYgI3PL3gduYSQkNDY4xMTU0NBjWromGd6lBXV/+tUTNg/S0+HpzGBVI6YD1z+QbOXLyupKaro40hvTpBV1cnjYty+BSgAAUoQAEKUIACFKAAV7DyGaAABSigYgI+fv5wPnQSH3x8lUaWL08udGzVFDmyZ41z1AEB36GlpQUtLc2fzooBq4rdcA4nRQVSMmB1dT+H655eSvPLljULBvXoAE3Nn/+cpigKL0YBClCAAhSgAAUoQAEK/JYAA9bf4uPBFKAABZJHICw8HB7nr+LidU+lC2hpaqK5kQGqli8T4zu/z1+wfrsDcuXIhkE9zRmwJs+t4VnTuEBKBax2+1wh6ivHboUL5EWvTm3SuCKHTwEKUIACFKAABShAAQpEF2DAqiLPw5t377HJygbXPe/is/9nFClcCFUqlEf3Lh1QqGDqbHxhaGKGdq1bYMKoYVLJynY3NlrZxBDLkT07KlUoi/69LFChXMywJyG0R094YP3WHXj77j02rlyIyhXKxThs30FXzF+2BtvWLUW5MqUTckqlPucuXsGWHXZ49vwF8ubNgzYmxujWyQwaGj9esw4PD8c2293Y7+oGX18/FNMvgr49usCoYf0Y5wsNC4ONnROOHD+JDx8+oqh+EfTp1hmNG9b7pbHxIArEJ/Di1Vvsc3XHt4DvSl1LF9dHm+YNoaujIzfO2Wa/H+8+fpL9+nc3Q95cOeM8PVewxqfO79OzQHIHrOLfJ5tsneHr/1mJsUr50jA1bpieeTk3ClCAAhSgAAUoQAEKZEgBBqwqcNv9/PzRY8AIfPsegGZGDSFeHXz2/CUuX7uBnDlyYN+urb9dc/FXplnPuB3atm6ByWOHy8M3b9+FLdt3oWvHdsiSJTPCw8Lw8tUbnD5/Eepq6li/bB7KlimV4Et9/RaAdl37oEihgjAxNoJpi6bIkSO74vjvgYHobDkE1atUwOypExN83ugdr964heHjp6B6lYowrFcXnve84H76HAb17SkD1Ki2ZtM22Ng7yUC1bOmS8Dh7AV4PH2P5/BmoU7OGot/CFWvhvP8IjI0aolyZUjh15hw87z3AnKkT0LSx4S+NkQdRID6BwKAgHDh2Go+evVTqmlkvE9qbGOG592ucvXxT8X3jejVRr2bVOE/NgDU+cX6fngWSM2ANDA7GJhtHfAsIVCIUNZSN6tVMz7ScGwUoQAEKUIACFKAABTKsAANWFbj1UcHl+uULUK1yBcWIXr1+iw+ffGQ4mBrtZwHrPrutyJcnj2JInnfvY9CoiTA0qI2Fs6YkeKgPHj5G76FjMOOvcTBp1ljpOLFiduv2Xdi5dQ30CxdK8Hmjd5wwdTZueN7F3p1boZdJV3415q8Z8Hr4BIcctsu/DwkJQXOzbqhb6w8s+Gey/OxbQAAs+g5DqRLFsHz+P/Kzt+8/okP3fuhs1gZjhw+Sn4kVrb0HjUI4wrFry9pfGiMPokBCBW7de4hjpy4gJPYGWBERiFBTk6eJQATUoIbCBfOhl7lpnKdmwJpQcfZLjwLJFbD6f/mKzTudERISc4M6YdjSqD6qV475hkZ6tOWcKEABClCAAhSgAAUokFEFGLCqwJ2fPHMBLl6+iuP7d6vAaH4MIaEBqzhi5IRpuHPfC2777CB2O09Ii1pdumLBPzFWiYpj/f0/o5PlIJg0a4LxIwcn5HRx9hHhr3i1um6tH6tQN1jtwDbbPXA/6AAdHW08e+6Nbv2HYWh/S1h266Q4j1j56v3qNfbu2io/O3vhMsZPmYUNyxegarQgXJRN2LZzD04e2CPPx0aB5BTw8/8Cp8Mn8P6jj7xMBAA1+f/+DVcj1BChJv8WI/t3U/xiIfqYGLAm5x3iuVVdIDkC1ncfPsF6zwGI8gDRm/g57NS2OUoVK6LqLBwfBShAAQpQgAIUoAAFKPAbAgxYfwMvqQ5dvHIDHF0OIvYK1rjOHxYWDitbOxxyPQ6x03ixovro16MLGhv+qAH6yccHK9ZtxeVrNxEYGIii+oXR0tgIHdu2VgSACemTmIB1+drNsHdywbF9dsiSWU++Ri9ep182bwYMav+hNJVrNz3x57jI1aJRbdOqRYoarMvXbcb+Q0exZ8dG5MqRI07qkx5nsdt5P56+8EZIcDAKFSiAnhbmca6GjX6CcX/PxNPnL+Fks0l+7PXwEfoMHYvxIwbDvP2PFX8Tp8/Fjdt34OpkK/uJ64kwXClg3WYLKxt7GZBHrZJNqmeD56HAzwROXbiG81du/puwKv4nsvu/gauo9ShqPsZuDFj5XGVkgaQOWB8/94bDATdZBzl6U1dXR0/z1iiUP29G5ubcKUABClCAAhSgAAUokCEEGLCqwG0Wr8r3Gz5O1jFt0qg+qlauiErly8paoOIPaNHbklUijD0EszYmKFm8mKwVeuX6LSyZMw316kTWdhs9aTruP3yMnl06IneunLhz7wEuXLmKNUvmIH/eyD/oJaRPYgLWqFWhBx22y0D04NHjWLXBStYmrVlduQ5kwPdA7D9yFMvXbMaoIf1QoXw5lCtTUm7WIzb86tpnKPT0MkFTQxOaGuqyNurgfj2RSTfyNX/Rps5aCG0dbVSuUF7+/aFjx3H3/kPYbFqFEsX047yzt++IcgYT0K+XBQb27i77RH02beIYtGreRHHczPlL4X7mAk4ciFxZ/PyFNyz6DUNX83YYPXSA/EwE3n2GjMbnL1+wz85KBZ4mDiEjCXhcuIZzV25GlgWIWrb6I19F2VLF0LFVUyUSBqwZ6SnhXGMLJGXAesPTC0fczykha2lpYkD3DsieNQtvAAUoQAEKUIACFKAABSiQAQQYsKrITb528zZWrNuCB4+eKEYkNrgaPWwAWjRtJD8LCPgOkw7d0aVjW4wY3E9+Jmox9h06Brlz5YJ41V60Zm27wLhJI/z17+ZUcU0xIX0SE7Bu2W6Hzdt3wnnnVhTI96M+63/xRq1iXblwFmr/UU3RdeX6rdjlsBdVKpVHo/oGcrMpN/fTaNa4wX9udiWC2Y49BmDKhFEwbdFM6dJiU63eQ0ZBLDKy3bxKEdZev+mJYeMmY+60iWjSqIHiOLEC98BhN3gccVJ8NumfeTh1+rwMYsuWKgH3M+dx0/MeunUyw8ghkfeEjQIpIfD5yzdstHVCaGioou5q1HX/XcAKLU1NjB7YAxoaMX9Rw4A1Je4Qr6GqAkkVsJ65fANnLl5XmmYmXR0MtuwEXW2WjFHVZ4DjogAFKEABClCAAhSgQFILMGBNatHfPJ+Pnx/uez3C7bv34LT/CL58+YqNKxagcsXyePz0OXoOHIHRQ/ujWpVKiitZ73LA4yfPsNt6vfxs8OiJePT4KZoZNUSFsmVQrGgR+eq9traW4piE9ElMwBp7BWtCGH4WsLbt2gc5s2eH1bplimBIrNx12HdQzjH6hldid/V37z7ge2AggoJDMGT0RIwaNgAWHdspDeHvmQtw+txFrF8+HxXLl1V8r1jBOmksWhkbKT6fuWAZ3E+fV6xgFV+IkHvdlu04dfYCwsPCERIWiu8B32G/bR0KFsifkGmzDwV+W0C8irxiyy4EBgZB/MZAbHAl6rBG/FuMVU38FuHfWshd2rVAyaKFY1yTAetv3wKeIA0LJEXAetDtNG7ff6SkkDN7Ngzs0UHp7ZM0zMWhU4ACFKAABShAAQpQgAIJEGDAmgCk1Ory6Okz9Bo4Et07m8kVq5ev3ZCbScXVxOv0x13s5Vdv3n3Aqg1bITaR+vz5i/xMhH+iREDB/PkS3CcxAauomWrv+KMGa0LM4gpYxSrT5u0tMMCyO/pbWihOc+P2XQwdMwnzp/+Fxg0j681ust4J291OCAoKjnG5uAJWUVZh8cr1GDN8ILqYtY3R//6DR+g7LP4arLHn9MnXF517DUY70xaKkgEJmTf7UOB3Ba573oer+/kEnaZ1M0NUrVAmRl8GrAmiY6d0KvC7AesOx4N49ea9kk7xIgVhYdYynapxWhSgAAUoQAEKUIACFKDAfwkwYFXh50PU9zRqbY5WLZpi8rgRihWs8/+ZjMYNDBI0chGwitWWc5esilE7NPrBP+uTmIB11MTp8Lx7D24u9lD7d+VcfAOMK2AVK0Sbtesq66OKOqlRLSpgFbVm69etBVFS4c9xf2NIv14wNmqIwoUKQKxmbWLaWWkFqyi7MHDk/1C/bm3Mmz5JaVjPnnujW/9hGDagN3pZmCu+H/G/KXjx8tVPa6suXrEerifc4bB9I7JnzxbfdPk9BZJM4P1HH7ifu4KgkBDkyJYVOlpa0NbRgo6WduT/amvLz3R1daBfSHllNQPWJLsVPFEaFPjVgDU8PBzrdzji85evSrOuUbkcTIzqp0ENDpkCFKAABShAAQpQgAIUSAoBBqxJofib5xD1SzNl0pW1VTU1NBRnO3rCA9PnLsbY4YPQ2awNxMZQLcwsYGRYL0Yt0pfer6GnpyvrsIomVq5Wr1I5Rt3FNp17o2GDupg4eliC+yQ0YL17/wEGjpwAg9p/yM22Etp+ViKgk+Ug6GXSg9XapYo5LFu9Cbv37lfUeBXlAkTZADcXO2TW05OXFA5d+gyJEbCKwLbPsDEQfzC2WrsMWbNkVhpeSEgIjNtboF7dWnKFrGjiOLGhVYliRRW1baMf+PLVa3Tv9ycG9ukBy26dEjpl9qOASggwYFWJ28BBpJLArwSsohzHBhtHfBdlOWI1w7o1YFi7eirNhpelAAUoQAEKUIACFKAABVRBgAFrKt8Fsepy8KiJcnOrvHlyo2ql8ihcqCCePX+J0+cvobh+EVmLVEcncrMMsWrScf8hNDCojT+qVcHr129x6NgJNDMyxN/jR8Lz7n0ZdpYuUVy+Sp8jezacv3gV5y5dwbJ5M2QImpA+4lo/C1jFhk5Zs2ZBWFgYXr95i5Me5+QmO+uWzkOFcpGvIh8+dhJrNm7DzCnj5Tjjaj8LWI8cd8c/85aiepWKaNTAAA8fPcFhN3eYtWmpCIhved6TtWaFQ7PGhnKjnz3OB/DwydMYAeucxStx4IgbzNu2RrkyJX8MQ00NLZs3kZsAiSZKKuzcsxfGjQ1RrmxpWXv1zn0vLJ07HfXq1FQa/pRZC3Drzn1ZE1ZXRyeVnyJengKJE2DAmjgv9k5fAokNWH39PmOL3V6EhoYpQZgaN0SV8qXTFxBnQwEKUIACFKAABShAAQokWoABa6LJkv4AsbpShIBnL1zGwyfP4O/vj0IFCqBe3ZroZdEpxqrL0LAwWNnYy1DV3+8zShYvhgYGtWDZrbNiteeV67fg4HIQDx4+kecqUqQwenbpgOZNGikGn5A+hiZmaNe6BSaMilz1amW7GxutbGIAiFfjK5Uri36WXVGpfDnFd04uh7Fo5bqfBpSi403Pe3JTqjVL5uKPapVjnNft1Bns2OUgV6XmyZMLrYyboKeFuSIQFZ33HXSFzW4nfPrki+LF9NG3Z1fMmLsYQwf0Rqf2pvJ8loNGydA1rubqZIts2bLKr0Q5hq02djh4xA2+/v5yI62+PbrK4Dp2e/DwMXoPHSMD7TYtjZP+geAZKZDMAgxYkxmYp1dpgcQErK/ffYCNw0GEi43jojVRCqdr+xYoXqSQSs+Vg6MABShAAQpQgAIUoAAFUkaAAWvKOPMqFKAABVRGgAGrytwKDiQVBBIasD548hzOh04gZrQK+ctMy05tkD9v7lQYPS9JAQpQgAIUoAAFKEABCqiiAANWVbwrHBMFKECBZBRgwJqMuDy1ygskJGC9fPMujp++qDQXHW0tDOjeEVmzRNb+ZqMABShAAQpQgAIUoAAFKCAEGLDyOaAABSiQwQQYsGawG87pxhCIL2B1P38VF67eUlLLrKeLwT07Q1s7snY3GwUoQAEKUIACFKAABSjw//buPe7L+f4D+DtRMZFyytkakkOGbQ6lWmpyiIgUESWnaZgcfg6hKFsOiwzJuRDWYTqQnMZssx9Wk5CwHBKG2dJh9Htc1373V+nO93t9d9/cXffz+q/v9b4On+f70z+vx+f+XAQqBASs5gIBAgRqmYCAtZY13HBLDljHP/R4vPTqivt2r9943Tj+yENitdVWo0mAAAECBAgQIECAAIEVBASsJgUBAgRqmYCAtZY13HBLClhvHzMh3p3/4XK1yf6rzbbaLI44sANFAgQIECBAgAABAgQIrFRAwGpyECBAoJYJ1LSA9YbbRsewG29brgvrrtMwWmy3TfQ7sVe03KF54VzvfufEvPkfxMR7Rq7QtUt+8asYO/HheOGJiYVzO7XaLz7//IvCv5MPFG25+abRsW3r6NurezSoX79o95Pr2x3cI+rVWyOmPnBHJF+Qr87j8ONOjU2bbhzXXH5h4THJb2uttWbcPnxodT46vfe/FiyIH7Q/JE7t0zNO7d2z2p/3TT+gsi0C7rj/wXhn3vsrvMruLVvEvq1/9E2/oucRIECAAAECBAgQILCKCQhYV7GGeV0CBAj8twI1LWAdPvLOGH7znXFMty7RsOHasXTp0vj7Rx/HQ4/+Lj75x6dx94hfxU4ttkuHfeypZ8V78z+IKfctH8gm5y4cfHWMm/hQzHhqSoGoxZ4do/k2zaJ9m73S3xYvXhJ/femVeObZ56Jdqz1i+C8vLcqZ1Pbud25aN/qma2KXnVoUvea/KTj0mJNj06YbxbVXXFy4zdDrRkS9evWiX99j/5tbr3Dt3b/5bfxlxswYMuCcwrlFixZH/wGDo1OHttGpfZsqfV5NuNlXA9YFCxfFsJtHL/dqS2NptN3rB7HnrjvVhFf2DgQIECBAgAABAgQI1HABAWsNb5DXI0CAQFUL1NSA9bEJo2OjDdYvDHf++x/Ggd17x64td4wbrhyU/l5OwHpY504x8LwzlmNMAstbRt0XY265LnbcftuvJb5o8NUx6ZHHY8niJdG9a+c492cnVXVLlrtfZQFrdT0wWfU77Ynfx5MT762uR9S4+1a2gvWaEaNi4aLFhXft3LFNtNj2uzXu3b0QAQIECBAgQIAAAQI1U0DAWjP74q0IECBQbQKrSsCaAJx45vkxe84bMW3cqCoNWKfPnBVH9u4Xg87/eRx64E9Wav3vzz+P1vsfEfvs+cN0Ne0rr70e08bdVa3bBHyTAeuAIdfEtCd/H09NGlNt862m3biygPX99z+KsVMejYVLFsehndrHZk03rGmv7X0IECBAgAABAgQIEKjBAgLWGtwcr0aAAIHqEFiVAtYkbKyzWp144LbrqzRgTULF0865ON0iINkqYGXH03/83zjh9PNi2JAB8ckn/0i3IUi2LGi54/aFS5559vlI9oa9ctD5cf/4yTFj5qxouPZ3okfXg6P30UcU6pJ9Zu8YMzaGXnJe/PrWUTF7zpuxxWabxOknHRdt9v5yn8/KAtajTzwj3YP1pqsvL9zvxVmvxlXX3xzTX3w51m+8Xuy9x25x1k9PKOwr+/Bjv4s77x0br73xt1i8eHFstknT6NOzWxz4kx+n90hWr9479sv9ao/r0TX6n9Y3lixZEt9ve1D6Xkl9xTF52hMx4vZ74vW/zY0m6zWKzp06xCm9j47V69ZNS5Z1eGDClJj+4kux4QZN4uTjjo4DOrarjqlc1j0rC1jLupGLCBAgQIAAAQIECBAg8P8CAlZTgQABArVMoKYGrMkq1aYbbZB246OPP4k7x4yLG24dFScdd1Rh79Fki4CXX50TvXp0XaFrUx9/Kl6ZPWeFPViTFarJStXkWPLvf8fMWa/GuZf+In1Gspdro3XXWekMuOCyK2PyI0/E01Pui88+WxitD+gWPbt1iXP6nVi45qk//Dn6nvE/scYaa0Sn9vvEVltuHtOeeDqSAHTZFbJXXT8ybr7z3mi8XqM4sGO7aNCgQYyfNDU+/PtHMWH0iNhqi83Se1YWsHbv0y8NWEcOuyKteeudeXFIzxOj0ToN46D92seiRUtizLgHo0O71jH4wv5pzc8vuCzq1a8Xu+z4nz1jx016OGbMfDnGj7opmm21Rbz97ry4/Krr488vzIjrhw6MTTbeKPVP9qndpc0B6QfGTurVI702sf3ZeZem2yn8uPWe8fLs1+OhR5+MIw45IC4+52dpTYVD/fr1ossB2p3kUwAAEQFJREFUHaPpRhvGuElT4/U358a9I68t7KP7bf93E7B+2x3wfAIECBAgQIAAAQL5ExCw5q+nRkSAAIGvFaipAWtlL916zx/EtUMujnr11khPJwHrs89NX+n46tZdbYWAtbLiZIXp4IvOTsPClR1JGJtsD7D3D3dLV6dWPP+tt9+NR8Z+uU1ARbB4bPfDCsHrvxYsiAOP7BPf++6WMeKawem1FQHrsqtmX3p5dhzW65Q44+Tj44RjjkzrSglYrxx+c9x+9wMx9q4b07A0OWa//mZs0KRxrLtOw0qH9M6892LfLj3j8gvPikP275jWVLYHa2UB61EnnpEGwWPvvCHWbNAgvfa8gb+M306ZFs889EC6YrfC4ad9jklXtibHu++9H/t2OTqOP+rw+PmpfWrE/0wBa41og5cgQIAAAQIECBAgkCsBAWuu2mkwBAgQKC5QUwPWY7p1iYYN104HkISE22/7vdit5Y7LDSgJWN+dNz8efuCOFQaarDYdP3nqCgFr822aRfs2e6X1devWjS02bRp77P79dCXp1x1PPvOnOOnMC+KqQRfEfu33SUtH3Tc+LrtqeNx987BouUPz9LeKYPGayy+Mju1aF26ZbEEw5825MfGekelvFQHr76fcv9yq2R916BL7d2gbA87+z0rQUgLWfuddEq/OfiMm33fr145h4aJFqdeCzxbGosWLI9lq4NzTT47EOjlKDVj32q9r7Ntm77h0mY+FTZn2ZJx5waC4/7bh0WK7bQoOtw3/Zfxw15aF92rXuUfststOMfTS84pPzm+gQsD6DSB7BAECBAgQIECAAIFaJiBgrWUNN1wCBAjU1ID1sQmjY6MN1v/aBiUB63vzP0j/tP+rR7I/6riJD60QsB7WuVMMXCYYLHUGJCs0kz/hT/5MPvnz/OR4/4O/x51jxkav7l3j7H59098qAtZbrv1F7LH7LoXbXzT46vTP6P84dWz6W0XAOuOpKZGstK04Oh1+XLrS9dorLk5/KiVgTVaUfvHFF+l+sCs7rh1xR9wyakwsWrR4uZKsAWvyoa+dW3VKV9gmK20rjmefnx7HnnJW/HrowHQP2QqHu268OnbdeYdC3X6H94odmm8bVw78n1Lpq7VOwFqtvG5OgAABAgQIECBAoFYKCFhrZdsNmgCB2iwgYC3e/eRDT632PyI+/ee/Ki3eZOMN020CkqMiWEwCxE77ti3UJytYkw9MTbr3lvS3ioD1yYn3ph+lqjiSFazJdRV7mZYSsBZbwfqn5/4SvU7tn36oKrn35ps2jWQ1665tD6r2FawC1uLzSwUBAgQIECBAgAABAvkSELDmq59GQ4AAgaICAtaiRPH4U3+IU/pfFMOGDEj/NH7Z477xk2LAkGvinpHDYucWzQsB67If06rYg7XZ1lvGzb9afg/WIRedHZ077Zve8qVXXovDjj05DUL7Hts9/S359wZNmsQNVw0qPParH7mq2IM1+WDV1ltuntYlH5Nav0njdD/U0fdPiEFXXhfPThsX31lrrfT8m3Pfjk5HHLdcwDpw6HUxYfIj8adHxkadOnXSusr2YO3R9/T0o2DJHqwN6tdP684fNDTGT34kki0P1mm4thWsxaeVCgIECBAgQIAAAQIEciogYM1pYw2LAAECKxMQsBafG+deckU88sTT8fTk+6N+/XrLXZAEjfsc2C2O6XZo9D+tbyFYXGP11eMn7feJbZttHVMffypmzHw53Zog2aIgOSpWsCb7yx68f4dYa801Y9zEh+P9Dz+M8XeNiO9u9Z+gNNn39bnpf43kY1Hdu3aO5L5fDVj/9tY70aXnSdGkcaP0Xsk2AKMfmBAd2raKwRf2j+envxjJNgLJn+53at8mkg923TVmXLw8e85yAevIu8ZEEtYedfjBcXCnDrHj9ttWGrAmWx2ccf6gaLnj9tF+n71i1qtzYtLUx6Jr506FfVltEVB8XqkgQIAAAQIECBAgQCCfAgLWfPbVqAgQILBSgZoWsN5w2+gYduNt8eSD96QrML/u6N3vnJg3/4PCh6OWrU0+2DR24sPxwhMTCz/v1Gq/NASs+IBUKdPi88+/iD06Hhrt99kzhgw4p9JLTjzz/JjzxtyY+ps7CgHrZRecFQ8+9GjMmDkrXTXa/bCDCqtSKwLWW0ffF9cOuTiuv+WumD3nzdhs06bpvqbtWu1ReM5z01+MJOB9+9330tWhSSCbfJwq2Qf2pqsvL9RNnzkrrr7+lvR5TRqvF61+tHucddoJsWaDBmlNstI2CVCTfWObbb1FnHz80dH/osvjzFP6RI+undOaT/7xaZxx/sBIntnjsIPTfWWT7RG+3/agdFVtn57dCs9LAtWbbr8n3pj7VjRulAS7+8apfY6J1evWTWueefb5SPqz7AfAkt/373Z87LT9dnHFxZVbltKTqqyxB2tVaroXAQIECBAgQIAAAQKJgIDVPCBAgEAtE6hpAeuqzr+ylZtfHVeygjUJWJOPXDm+PQEB67dn78kECBAgQIAAAQIE8iogYM1rZ42LAAECKxEQsFbt1BCwVq1ndd9NwFrdwu5PgAABAgQIECBAoPYJCFhrX8+NmACBWi4gYK3aCSBgrVrP6r6bgLW6hd2fAAECBAgQIECAQO0TELDWvp4bMQECtVxAwFq1E+APf34hjj/t7Lhn5LDYuUXzld582E23p1sEPP/4g1X7Au6WSUDAmolLMQECBAgQIECAAAECJQgIWEtAUkKAAIE8CQhY89RNY8kqIGDNKqaeAAECBAgQIECAAIFiAgLWYkLOEyBAIGcCAtacNdRwMgkIWDNxKSZAgAABAgQIECBAoAQBAWsJSEoIECCQJwEBa566aSxZBQSsWcXUEyBAgAABAgQIECBQTEDAWkzIeQIECORMQMCas4YaTiYBAWsmLsUECBAgQIAAAQIECJQgIGAtAUkJAQIE8iQgYM1TN40lq4CANauYegIECBAgQIAAAQIEigkIWIsJOU+AAIGcCQhYc9ZQw8kkIGDNxKWYAAECBAgQIECAAIESBASsJSApIUCAQJ4EBKx56qaxZBUQsGYVU0+AAAECBAgQIECAQDEBAWsxIecJECCQMwEBa84aajiZBASsmbgUEyBAgAABAgQIECBQgoCAtQQkJQQIEMiTgIA1T900lqwCAtasYuoJECBAgAABAgQIECgmIGAtJuQ8AQIEciYgYM1ZQw0nk4CANROXYgIECBAgQIAAAQIEShAQsJaApIQAAQJ5EhCw5qmbxpJVQMCaVUw9AQIECBAgQIAAAQLFBASsxYScJ0CAQM4EBKw5a6jhZBIQsGbiUkyAAAECBAgQIECAQAkCAtYSkJQQIEAgTwIC1jx101iyCghYs4qpJ0CAAAECBAgQIECgmICAtZiQ8wQIEMiZgIA1Zw01nEwCAtZMXIoJECBAgAABAgQIEChBQMBaApISAgQI5ElAwJqnbhpLVgEBa1Yx9QQIECBAgAABAgQIFBMQsBYTcp4AAQI5ExCw5qyhhpNJQMCaiUsxAQIECBAgQIAAAQIlCAhYS0BSQoAAgTwJCFjz1E1jySogYM0qpp4AAQIECBAgQIAAgWICAtZiQs4TIEAgZwIC1pw11HAyCQhYM3EpJkCAAAECBAgQIECgBAEBawlISggQIJAnAQFrnrppLFkFBKxZxdQTIECAAAECBAgQIFBMQMBaTMh5AgQI5ExAwJqzhhpOJgEBayYuxQQIECBAgAABAgQIlCAgYC0BSQkBAgTyJCBgzVM3jSWrgIA1q5h6AgQIECBAgAABAgSKCQhYiwk5T4AAgZwJCFhz1lDDySQgYM3EpZgAAQIECBAgQIAAgRIEBKwlICkhQIBAngQErHnqprFkFRCwZhVTT4AAAQIECBAgQIBAMQEBazEh5wkQIJAzAQFrzhpqOJkEBKyZuBQTIECAAAECBAgQIFCCgIC1BCQlBAgQyJOAgDVP3TSWrAIC1qxi6gkQIECAAAECBAgQKCYgYC0m5DwBAgRyJiBgzVlDDSeTgIA1E5diAgQIECBAgAABAgRKEBCwloCkhAABAnkSELDmqZvGklVAwJpVTD0BAgQIECBAgAABAsUEBKzFhJwnQIBAzgQErDlrqOFkEhCwZuJSTIAAAQIECBAgQIBACQIC1hKQlBAgQCBPAgLWPHXTWLIKCFiziqknQIAAAQIECBAgQKCYgIC1mJDzBAgQyJmAgDVnDTWcTAIC1kxcigkQIECAAAECBAgQKEFAwFoCkhICBAjkSUDAmqduGktWAQFrVjH1BAgQIECAAAECBAgUExCwFhNyngABAjkTELDmrKGGk0lAwJqJSzEBAgQIECBAgAABAiUICFhLQFJCgACBPAkIWPPUTWPJKiBgzSqmngABAgQIECBAgACBYgIC1mJCzhMgQCBnAgLWnDXUcDIJCFgzcSkmQIAAAQIECBAgQKAEAQFrCUhKCBAgkCcBAWueumksWQUErFnF1BMgQIAAAQIECBAgUExAwFpMyHkCBAjkTGDma3Pj8y+Wxq7Nt4q1GtTL2egMh8DKBRYsXBzPzXoj6q5WJ1o02xwVAQIECBAgQIAAAQIEqkRAwFoljG5CgACBVUfgtbnzIgma1m+0dmzZdP1Ys76QddXpnjctV+CzRYvjzXc/iA8+/mes2aBefG/zjcu9lesIECBAgAABAgQIECCwnICA1YQgQIBALRP4dMHCeOPt+bVs1IZL4EuBrTbdMBqu1QAJAQIECBAgQIAAAQIEqkRAwFoljG5CgACBVUsgCVnf+/DjWLRoSXyxdOmq9fLelkAZAqvVqRMN6q8RGzZpJFwtw88lBAgQIECAAAECBAisXEDAanYQIECAAAECBAgQIECAAAECBAgQIECgTAEBa5lwLiNAgAABAgQIECBAgAABAgQIECBAgICA1RwgQIAAAQIECBAgQIAAAQIECBAgQIBAmQIC1jLhXEaAAAECBAgQIECAAAECBAgQIECAAAEBqzlAgAABAgQIECBAgAABAgQIECBAgACBMgUErGXCuYwAAQIECBAgQIAAAQIECBAgQIAAAQICVnOAAAECBAgQIECAAAECBAgQIECAAAECZQoIWMuEcxkBAgQIECBAgAABAgQIECBAgAABAgQErOYAAQIECBAgQIAAAQIECBAgQIAAAQIEyhQQsJYJ5zICBAgQIECAAAECBAgQIECAAAECBAgIWM0BAgQIECBAgAABAgQIECBAgAABAgQIlCkgYC0TzmUECBAgQIAAAQIECBAgQIAAAQIECBAQsJoDBAgQIECAAAECBAgQIECAAAECBAgQKFNAwFomnMsIECBAgAABAgQIECBAgAABAgQIECAgYDUHCBAgQIAAAQIECBAgQIAAAQIECBAgUKaAgLVMOJcRIECAAAECBAgQIECAAAECBAgQIEBAwGoOECBAgAABAgQIECBAgAABAgQIECBAoEwBAWuZcC4jQIAAAQIECBAgQIAAAQIECBAgQICAgNUcIECAAAECBAgQIECAAAECBAgQIECAQJkCAtYy4VxGgAABAgQIECBAgAABAgQIECBAgAABAas5QIAAAQIECBAgQIAAAQIECBAgQIAAgTIFBKxlwrmMAAECBAgQIECAAAECBAgQIECAAAECAlZzgAABAgQIECBAgAABAgQIECBAgAABAmUKCFjLhHMZAQIECBAgQIAAAQIECBAgQIAAAQIEBKzmAAECBAgQIECAAAECBAgQIECAAAECBMoUELCWCecyAgQIECBAgAABAgQIECBAgAABAgQICFjNAQIECBAgQIAAAQIECBAgQIAAAQIECJQp8H+j6aBn37IDuAAAAABJRU5ErkJggg==\" alt=\"Vigolante\"></p>\n<p>The idea behind it can fit in one sentence: it’s an authentication layer, which uses the same cookie as Admin, gets a session identifier from a frontend request, connects to the sessions storage (Memcached), fetches a session data, gets a OAuth token from the data and, enriches the initial request with the token and then forwards it to a Gateway.</p>\n<p>Quite a simple flow, but once in place helped us to save a lot of development time in order to deliver new features to Admin. From now on, we don’t need to make any changes in Admin, when we need to send a request to a microservice from Frontend.</p>\n<p>We have chosen <a href=\"https://golang.org/\">Golang</a> as an underlining technology to build the project. The reasons are: </p>\n<ul>\n<li>it's fast. It adds only about 10ms of overhead per request.</li>\n<li>it's small. The resulting docker image is only 1MB big!</li>\n<li>it's fun. We gave ourselves a break from Java or PHP.</li>\n</ul>\n<p>Basically, the project was developed by the efforts of 4 engineers in a bit more than one day. We are proud to say, that this time was not just for coding but also for taking care of bringing the software to production; things as:</p>\n<ul>\n<li>build/release pipelines (as a code). We use Jenkins in AUTO1, and our pipelines should be delivered in a form of Groovy-based <a href=\"https://jenkinsci.github.io/job-dsl-plugin\">Jenkins DSL code</a>.</li>\n<li>Infrastructure (as a code). We using AWS services, and the application was prepared as a Docker container, <a href=\"https://aws.amazon.com/ecr/\">ECR</a> was used for as a container registry, <a href=\"https://aws.amazon.com/ecs/\">ECS</a> as a platform to run a container. All this was described in a form of <a href=\"https://www.terraform.io/\">Terraform</a> configuration</li>\n<li>Integration with platform, done in a form of a listener for <a href=\"https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html\">Application Load Balancer</a> (ALB) for main Admin platform host. So, basically, every request with a certain prefix was directed to Vigolante, instead of Admin.</li>\n</ul>\n<p>There were few things yet to be resolved (such an implementation of mechanisms of refreshing of OAuth tokens, also there were some problems with encryption of PHP sessions from Memcached), but those were successfully resolved; one month later we released the first feature relying on Vigolante to production.</p>\n<p><strong>Feeling proud and fulfilled, we could now focus our attention on the our engineering challenges.</strong></p>","fields":{"slug":"/vigolante/","tags":["golang","microservices","monolith","PHP","back-office"]}}},{"node":{"id":"f1483025-8f93-596d-89a4-e459c4718414","frontmatter":{"category":"Coding","title":"Database Transaction Isolation","date":"2018-06-20","summary":"What is transaction isolation level? What are differences? What are the default values for RDBMSs?","thumbnail":{"relativePath":"pages/transactionisolation/thumbnail.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsSAAALEgHS3X78AAABIUlEQVQoz5VS7U7DMAzsa6A1cRynTT/WrTBNiB8gJN7/mczFVWHTWiF+nM750OXsS8XMGjhqbDplaRZuMupWKSZ1zqn3/g5EtIsqBNIAoTRdNeajpuPFIMOs0p+0Pjypqw9AvbADQ7Q8tAUIBg1wwk0PwdGEuO2VUTPcynAGnrE3GlNsFnHnH5wXVGvLQbLmy4ehe/3SfP20OnWTpmHQbh41n9BB32IvquS4OQ4TpLIgj7mhDh6OyyPB1t47c1TYu4UJYyr3dwXtgGpNmSFCgDdOHcbBZO3dw/2I3da/Dlm0nd8ww0ljf14CAsv4gofCppNV7MGhoD1uB8zrHa2wfZUSRuGSvve0K7gZSkrpJvZ6wfo9LE2362ZTUET+vPwfh9/1JBQjnS3wvwAAAABJRU5ErkJggg==","width":677,"height":325,"src":"/static/2691083d1efbcb8a271d80bf9ff6940f/b3029/thumbnail.png","srcSet":"/static/2691083d1efbcb8a271d80bf9ff6940f/b3029/thumbnail.png 1x"}}},"authorName":"Hayk Jhangiryan","authorDescription":"Hayk is Senior Java Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/transactionisolation/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/transactionisolation/header-image.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsSAAALEgHS3X78AAABIUlEQVQoz5VS7U7DMAzsa6A1cRynTT/WrTBNiB8gJN7/mczFVWHTWiF+nM750OXsS8XMGjhqbDplaRZuMupWKSZ1zqn3/g5EtIsqBNIAoTRdNeajpuPFIMOs0p+0Pjypqw9AvbADQ7Q8tAUIBg1wwk0PwdGEuO2VUTPcynAGnrE3GlNsFnHnH5wXVGvLQbLmy4ehe/3SfP20OnWTpmHQbh41n9BB32IvquS4OQ4TpLIgj7mhDh6OyyPB1t47c1TYu4UJYyr3dwXtgGpNmSFCgDdOHcbBZO3dw/2I3da/Dlm0nd8ww0ljf14CAsv4gofCppNV7MGhoD1uB8zrHa2wfZUSRuGSvve0K7gZSkrpJvZ6wfo9LE2362ZTUET+vPwfh9/1JBQjnS3wvwAAAABJRU5ErkJggg==","width":838,"height":402,"src":"/static/2691083d1efbcb8a271d80bf9ff6940f/d5ccc/header-image.png","srcSet":"/static/2691083d1efbcb8a271d80bf9ff6940f/d5ccc/header-image.png 1x"}}}},"html":"<h1>Database Transaction Isolation</h1>\n<h2>What is transaction isolation level?</h2>\n<p>Transaction isolation level defines the degree to which one transaction must be isolated from resource or data modifications made by other transactions. </p>\n<p>Let's have a look at phenomena which can occur during the execution of concurrent transactions:</p>\n<ul>\n<li>\n<p>Dirty read - A transaction may read data written but not yet committed by other transactions.\n           <p>example: Transaction T1 modifies a row. Transaction T2 then reads that row before T1 performs a COMMIT. If T1 then performs a ROLLBACK, T2 have read a row that was never committed and that may be considered to have never existed.</p></p>\n</li>\n<li>\n<p>Nonrepeatable read - A transaction re-reads data it had previously read and finds that data has been modified by another transaction (that committed since the initial read).\n           <p>example: Transaction T1 reads a row. Transaction T2 then modifies or deletes that row and performs a COMMIT. If T1 then attempts to reread the row, it may receive the modified value or discover that the row has been deleted.</p></p>\n</li>\n<li>\n<p>Phantom read - A transaction re-executes a query returning a set of rows that satisfy a search condition and finds that the set of rows satisfying the condition has changed due to another recently-committed transaction.\n<p>example: Transaction T1 reads the set of rows N that satisfy some <em>search condition</em>. Transaction T2 then executes SQL-statements that generate one or more rows that satisfy the <em>search condition</em> used by transaction T1. If transaction T1 then repeats the initial read with the same <em>search condition</em>, it obtains a different set of rows.</p></p>\n</li>\n</ul>\n<p>Isolation is the <em>I</em> in the acronym <a href=\"https://en.wikipedia.org/wiki/ACID\"><em>ACID</em></a>. In ACID, atomicity and durability are strict requirements. Whereas consistency and isolation are more of configuration (kind of). Besides, they are closely related, so much so that the SQL standard defines four levels of transaction isolation based on the consistency they provide (from least to the most consistency):</p>\n<table>\n<thead>\n<tr>\n<th>ISOLATION  LEVEL</th>\n<th align=\"center\">DIRTY READ</th>\n<th align=\"center\">NON-REPEATABLE READ</th>\n<th align=\"center\">PHANTOM READ</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>READ UNCOMMITTED</td>\n<td align=\"center\">possible</td>\n<td align=\"center\">possible</td>\n<td align=\"center\">possible</td>\n</tr>\n<tr>\n<td>READ COMMITTED</td>\n<td align=\"center\">--</td>\n<td align=\"center\">possible</td>\n<td align=\"center\">possible</td>\n</tr>\n<tr>\n<td>REPEATABLE READ</td>\n<td align=\"center\">--</td>\n<td align=\"center\">--</td>\n<td align=\"center\">possible</td>\n</tr>\n<tr>\n<td>SERIALIZABLE</td>\n<td align=\"center\">--</td>\n<td align=\"center\">--</td>\n<td align=\"center\">--</td>\n</tr>\n</tbody>\n</table>\n<p>Different isolation levels are defined based on whether they allow (or prevent) the above phenomena (as described by the SQL standard). Note that transaction isolation does not affect the changes made by the same transaction. It means a transaction always sees all the changes made by itself. </p>\n<h2>Now what?</h2>\n<p>Inside Java services, the transaction isolation level can be controlled by Spring <a href=\"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html\"><code class=\"language-text\">@Transactional</code></a> annotation which supports <a href=\"https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html#isolation--\"><code class=\"language-text\">isolation</code></a> attribute. If you do not specify the isolation level in the code explicitly, the default isolation level will be applied, which means that the default isolation level of the underlying datastore will be used.</p>\n<p>It is worth to mention that default isolation levels for each system might be different. For example, the default isolation level for <em>MySQL 5.7 (InnoDB)</em> and <em>PostgreSQL 9.5</em> is respectively, <em>REPEATABLE READ</em> and <em>READ COMMITTED</em>. To check the default isolation level, query:</p>\n<ul>\n<li><code class=\"language-text\">SHOW VARIABLES LIKE 'tx_isolation'; -- on MySQL</code></li>\n<li><code class=\"language-text\">SHOW default_transaction_isolation'; -- on PostgreSQL</code></li>\n</ul>\n<h3>References</h3>\n<ol>\n<li><a href=\"https://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-isolation-levels.html\">MySQL Transaction Isolation Levels</a></li>\n<li><a href=\"https://www.postgresql.org/docs/9.6/static/transaction-iso.html\">Transaction Isolation in PostgreSQL</a></li>\n<li><a href=\"https://dzone.com/articles/spring-transaction-management\">Useful article</a></li>\n</ol>","fields":{"slug":"/transactionisolation/","tags":["coding","sql","transactions"]}}},{"node":{"id":"c61acf9d-7746-503a-ba8f-cf96f4042096","frontmatter":{"category":"Coding","title":"Secure coding practices for NodeJS Web Applications","date":"2018-06-20","summary":"This post highlights various coding practices for securing a NodeJS web application against the most critical web attacks.","thumbnail":{"relativePath":"pages/securing-nodejs-applications/thumbnail.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHMkZoCv//EABUQAQEAAAAAAAAAAAAAAAAAAAAS/9oACAEBAAEFApSl/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BJ//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/AWf/xAAXEAADAQAAAAAAAAAAAAAAAAAAECEx/9oACAEBAAY/AoYv/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARIUFxUf/aAAgBAQABPyHOqLFGlciV85P/2gAMAwEAAgADAAAAEHvP/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAEDAQE/EAJs/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EFjP/8QAHBABAAEEAwAAAAAAAAAAAAAAASEAETFxUWHw/9oACAEBAAE/EMpW8q+4qwMgymddUsU0EV//2Q==","width":867,"height":325,"src":"/static/f21842b8ed2aa0a1b2cd57f6dbf9e7fc/a2998/thumbnail.jpeg","srcSet":"/static/f21842b8ed2aa0a1b2cd57f6dbf9e7fc/a2998/thumbnail.jpeg 1x"}}},"authorName":"Rajababu Pradhan","authorDescription":"Raja is Senior Frontend Engineer at AUTO1 Group.","authorAvatar":{"relativePath":"pages/securing-nodejs-applications/avatar.png","childImageSharp":{"resolutions":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAACyElEQVQ4y4VUO2gUURR9mZmN8YcItoKVjeXuzsxu9jOzm92NkBBTqDEmjZAEgtqIpSgI1gp+uhS6kEI7wc7GQsFCLERiISGCaGHhF02yu+M5s/cujyC4cJY379573r3n3XdNvV51xsYiJ4rKbqlUyBj8wjAYyWazp4BVYB3YAraBDeAhMBcE/l76lkrFTLVachuNyCGXEbJMrVbx6ADnaWAtn88nvu8nWBMdQcJ9Auv3wCxjWq2aC9IMSF3DzCyyG1YAs9pSYkL2melmLpfT71tKGkUlz2iZJAuCgA5dEjGAwPoV0AbuAy+tfR7YkZjb5CiXR1OutEw5jWQdCfgCnEiSxNg/7LWAj+KTSiHSzBvrAtascrriPCmnDkP4AYQ0Em3TGPHf8P38ARpP/4PsHQ7aU69Hqdi4OJeI47JXLg9IX1tVbUuWCzSsygcJO+L0goGNRpySoB1colarerhEvcCn4tuxCB/TsC5ZdS3Ct2Ho75uZmRoigWbIbgCxt7Q0O8TLsgg17o2R2+JHzzJcV/1IoBlybel42SLsCcc3I6UqoaZ+lUHFYjjCzJSQa+4J4UVLKiX8ScOGVXJXDN+xd7SfZXFYS65U+n2Wz+cOw+ezHadSkfCRdVJiZdlmMG9ZtHMpgWR3Z0eMSvWExjmrbXoCbZ951dIim7Yk6u1IYtlwavChW51Pp01tXOwf01eC9RHs/Rbbnx2Hf4IUh/Q5zdol8H3KG22Pj9edOK54LF1876pd37TELhqdZ+J4MwxDHUvXgDOFQrB7YqLpjI4WdhG8GLYNbCeBK/1+TWNWRG+Pfy5Hj5Dek3IXzX9+8DkL/AIeLC/PDU1NHXdSQk5altNsDkjPAT+ArzKyFnK5bB2IxbYik4hanmfM5GTL6Q/Y2DUc25y0HLToubR8TI39cL4APJOxr/35AXgOXEJnHKQvepP6eiQj119kDrZjqLo8HAAAAABJRU5ErkJggg==","width":50,"height":50,"src":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png","srcSet":"/static/26a7a327ccc4b335712e5a7086f2b26d/45876/avatar.png 1x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/eb85b/avatar.png 1.5x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/4f71c/avatar.png 2x,\n/static/26a7a327ccc4b335712e5a7086f2b26d/9ec3e/avatar.png 3x"}}},"headerImage":{"relativePath":"pages/securing-nodejs-applications/header-image.jpeg","childImageSharp":{"resolutions":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAIABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECBf/EABUBAQEAAAAAAAAAAAAAAAAAAAEC/9oADAMBAAIQAxAAAAHMkZoCv//EABUQAQEAAAAAAAAAAAAAAAAAAAAS/9oACAEBAAEFApSl/8QAFREBAQAAAAAAAAAAAAAAAAAAARD/2gAIAQMBAT8BJ//EABURAQEAAAAAAAAAAAAAAAAAAAEQ/9oACAECAQE/AWf/xAAXEAADAQAAAAAAAAAAAAAAAAAAECEx/9oACAEBAAY/AoYv/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARIUFxUf/aAAgBAQABPyHOqLFGlciV85P/2gAMAwEAAgADAAAAEHvP/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAh/9oACAEDAQE/EAJs/8QAFhEBAQEAAAAAAAAAAAAAAAAAARAR/9oACAECAQE/EFjP/8QAHBABAAEEAwAAAAAAAAAAAAAAASEAETFxUWHw/9oACAEBAAE/EMpW8q+4qwMgymddUsU0EV//2Q==","width":1200,"height":450,"src":"/static/f21842b8ed2aa0a1b2cd57f6dbf9e7fc/935ac/header-image.jpeg","srcSet":"/static/f21842b8ed2aa0a1b2cd57f6dbf9e7fc/935ac/header-image.jpeg 1x"}}}},"html":"<h1>Secure coding practices for NodeJS Web Applications</h1>\n<p>Everyone would agree that security is very important and with the increase in cyber attacks in the recent past, organizations are investing\nheavily on application security. In this post lets talk about securing a web application built in NodeJS.</p>\n<p><strong>NOTE</strong>: The security concepts discussed here are language or framework agnostic. However, here we will see how these practices are implemented\nin NodeJS web applications.</p>\n<h2>1. Use SSL/TLS for communication</h2>\n<p>It is always a good practice to send your data over HTTPS rather than HTTP and it is imperative if your app transmits sensitive data.\nEncrypting data transmitted between the client and server helps mitigate several attacks like <a href=\"https://www.owasp.org/index.php/Man-in-the-middle_attack\">man-in-the-middle(MITM)</a> attack, packet sniffing,\neavesdropping etc. Let’s see how to set up TLS/SSL in Express 4.x:</p>\n<p>Lets first generate a self-signed certificate:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365</code></pre></div>\n<p>This generates a self-signed certificate valid for 365 days.</p>\n<p><strong>NOTE</strong>: The self-signed certificate is not ideal for production. For production, you should get a certificate from a <em>Certificate Authority(CA)</em>.</p>\n<p>Next, enable HTTPS on Express. Additionally, redirect all HTTP traffic to HTTPS:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const fs = require('fs');\nconst https = require('https');\nconst express = require('express');\n\nconst NODE_ENV = process.env.NODE_ENV || 'development';\nconst PORT = process.env.PORT || 3443;\n\nconst app = express();\n\nhttps.createServer({\n  key: fs.readFileSync('/path/to/key.pem'),\n  cert: fs.readFileSync('/path/to/cert.pem')\n}, app).listen(PORT);\n\n// Redirect http requests to use https in production\nif (NODE_ENV === 'production') {\n  app.use((req, res, next) => {\n    if (req.header('x-forwarded-proto') !== 'https') {\n      res.redirect(`https://${req.header('host')}${req.url}`);\n    } else {\n      next();\n    }\n  });\n}</code></pre></div>\n<h2>2. Use security headers generously</h2>\n<p><strong>i) Strict-Transport-Security:</strong> <em>The HTTP Strict Transport Security(HSTS)</em> if set in the response header, tells the browser that it should only communicate using HTTPS instead of HTTP while communicating with the specified domain.</p>\n<p><em>Syntax:</em></p>\n<p><code class=\"language-text\">Strict-Transport-Security: max-age=&lt;expire-time></code></p>\n<p>Here, max-age is the time(in secs) that the browser should remember that this site is only to be accessed using HTTPS.</p>\n<p><em>Example: from facebook.com:</em></p>\n<p><code class=\"language-text\">strict-transport-security:max-age=15552000;</code></p>\n<p><strong>ii) X-Frame-Options:</strong> This HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <code class=\"language-text\">&lt;frame></code>, <code class=\"language-text\">&lt;iframe></code> or <code class=\"language-text\">&lt;object></code>. Sites can use this to avoid <a href=\"https://www.owasp.org/index.php/Clickjacking\">clickjacking</a> attacks, by ensuring that their content is not embedded into other sites.</p>\n<p><em>Syntax:</em></p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">X-Frame-Options: DENY\nX-Frame-Options: SAMEORIGIN\nX-Frame-Options: ALLOW-FROM https://siteutrust.com/</code></pre></div>\n<p><strong>iii) X-XSS-Protection:</strong> This HTTP response header enables the built-in XSS filter in modern browsers.</p>\n<p><em>Example:</em></p>\n<p><code class=\"language-text\">X-XSS-Protection: 1</code></p>\n<p><strong>iv) X-Content-Type-Options:</strong> This response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should not be changed and be followed. This prevents MIME type sniffing attacks.</p>\n<p><em>Syntax:</em></p>\n<p><code class=\"language-text\">X-Content-Type-Options: nosniff</code></p>\n<p><strong>v) Content-Security-Policy:</strong> Prevents a range of injection attacks including Cross Site Scripting(XSS) attack.</p>\n<p><em>Syntax:</em></p>\n<p><code class=\"language-text\">Content-Security-Policy: policy</code></p>\n<p>For a detailed explanation of CSP, go through this <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP\">link</a>.</p>\n<p>To set these headers in NodeJS, use the <a href=\"https://helmetjs.github.io/\">helmet</a> npm package:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const express = require('express');\nconst helmet = require('helmet');\n\nconst app = express();\n\n&lt;b>app.use(helmet())&lt;/b></code></pre></div>\n<p>This sets all the necessary headers in response.</p>\n<p>To set the headers individually:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">app.use(helmet({\n  frameguard: {\n    action: 'deny'\n  }\n}));</code></pre></div>\n<p>For an exhaustive list of security headers that should be set in a web application, check out the <a href=\"https://www.owasp.org/index.php/OWASP_Secure_Headers_Project\">OWASP Secure Headers Project</a>.</p>\n<p><strong>NOTE:</strong> In some web servers, the security headers can be set in the server configuration file itself. For example, in nginx server, we can set the above headers in <em>nginx.conf</em> as shown below:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">add_header X-Frame-Options DENY;\nadd_header X-Content-Type-Options nosniff;\nadd_header X-XSS-Protection 1;\nadd_header Content-Security-Policy \"default-src 'self'\";</code></pre></div>\n<h2>3. Preventing CSRF attacks</h2>\n<p><a href=\"https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29\">Cross site request forgery (CSRF)</a>, also known as <em>XSRF</em>, <em>Sea Surf</em> or <em>Session Riding</em>, is an attack vector that tricks a web browser into executing an unwanted action in an application to which a user is logged in. CSRF attacks specially targets state-changing requests and can force the victim to transfer funds, change email/password and so on.</p>\n<p>CSRFs are typically conducted using social engineering, such as an email or link that tricks the victim into sending a request to a server on behalf of the attacker. The server has no way to distinguish a forged request from a genuine one.</p>\n<p>In NodeJS, to prevent CSRF attack, we usually use the <a href=\"https://github.com/expressjs/csurf\">csurf</a> express middleware:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const cookieParser = require('cookie-parser');\nconst csrf = require('csurf');\nconst bodyParser = require('body-parser');\nconst express = require('express');\n\nconst csrfProtection = csrf({ cookie: true });\nconst parseForm = bodyParser.urlencoded({ extended: false });\n\n// create express app\nconst app = express();\n\n// we need this because \"cookie\" is true in csrfProtection\napp.use(cookieParser());\n\napp.get('/form', csrfProtection, (req, res) => {\n  // pass the csrfToken to the view\n  res.render('send', { csrfToken: req.csrfToken() });\n});</code></pre></div>\n<p>In the view use the CSRF token passed:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>form</span> <span class=\"token attr-name\">action</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/process<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">method</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>POST<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>hidden<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>csrf_token<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">value</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>{{csrfToken}}<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n\n  Enter amount: <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>input</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>number<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>amount<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>submit<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>Submit<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span>\n\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>form</span><span class=\"token punctuation\">></span></span></code></pre></div>\n<h2>4. Preventing XSS attacks</h2>\n<p>Cross-Site Scripting (XSS) attacks are a type of injection, in which malicious scripts are injected into otherwise benign and trusted web sites.\nAn attacker can use XSS to send a malicious script to an unsuspecting user. The end user’s browser has no way to know that the script should not\nbe trusted, and will execute the script. Because it thinks the script came from a trusted source, the malicious script can access any cookies, session tokens, or other sensitive information retained by the browser and used with that site. These scripts can even rewrite the content of the HTML page.</p>\n<p>The thumb rule to prevent this category of attack is to always validate and sanitize user data before processing or storing in database. Never trust data coming from user.\nValidation must be done on the server-side as client-side validation can be easily bypassed using tools such as Burp Suite, TamperData etc.</p>\n<p>A common approach to validate and sanitize user data is to use a library like <a href=\"https://github.com/chriso/validator.js\">validator.js</a>.</p>\n<p>Example: To validate an email</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">import validator from 'validator';\n\nif(validator.isEmail('foo@bar.com')) {\n  // Process email or store in DB\n}</code></pre></div>\n<p>This library provides a number of validators and sanitizers to filter user inputs.</p>\n<p>Other useful libraries include <a href=\"https://github.com/cure53/DOMPurify\">DOMPurify</a> and <a href=\"https://github.com/yahoo/xss-filters\">xss-filters</a>.</p>\n<p>Here is an example to sanitize user input using xss-filters:</p>\n<div class=\"gatsby-highlight\" data-language=\"html\"><pre class=\"language-html\"><code class=\"language-html\">const express = require('express');\nconst app = express();\nconst xssFilters = require('xss-filters');\n\napp.get('/', (req, res) => {\n  let firstname = req.query.firstname; //an untrusted input\n  res.send('<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span> Hello, ' + xssFilters.inHTMLData(firstname) + '!<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span>');\n});\n\napp.listen(3000);</code></pre></div>\n<h2>5. Preventing SQL Injection(SQLi) attacks</h2>\n<p>Passing unvalidated user input directly to a SQL statement is vulnerable to <a href=\"https://www.owasp.org/index.php/SQL_Injection\">SQL injection</a> attack.</p>\n<p>Conside the following example:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">// SQL query vulnerable to SQLi\nsql = \"SELECT * FROM users WHERE username='\" + username + \"' AND password='\" + password + \"'\";\n\n// Execute the SQL statement\ndatabase.execute(sql)</code></pre></div>\n<p>Now suppose the user enters the following in the username field:</p>\n<p><code class=\"language-text\">' OR '1'='1' --</code></p>\n<p>The above SQL statement becomes:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">sql = \"SELECT * FROM users WHERE username='\" + ' OR 1=1 -- + \"' AND password='\" + password + \"'\";</code></pre></div>\n<p>This effectively nullifies the need of a password and returns all the users in the database.</p>\n<p>This attack can be completely prevented by using parametrized or prepared statement.</p>\n<p>If you’re using an ORM to access the database (Mongoose, Sequelize etc), the ORM will normally take care of SQL injection by using prepared statements under the hood.</p>\n<h2>6. Secure cookies using cookie flags</h2>\n<p>XSS vulnerability in an application can be used to steal browser cookies. To prevent cookie stealing we can set the <strong>httpOnly</strong> flag of the cookie.\nAdditionaly, we can tell the browser to send cookies only over HTTPS using the <strong>secure</strong> flag.</p>\n<p><strong>secure :</strong> this attribute tells the browser to only send the cookie if the request is being sent over HTTPS.</p>\n<p><strong>HttpOnly :</strong> this attribute is used to help prevent attacks such as cross-site scripting, since it does not allow the cookie to be accessed via JavaScript.</p>\n<p>Example:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">app.use(session({\n  secret: ‘My super secret’,\n  &lt;b>cookie: { httpOnly: true, secure: true }&lt;/b>\n}));</code></pre></div>\n<h2>7. Preventing brute force and DoS attack</h2>\n<p>To prevent our site from overwhelming with a large number of requests, we need to put some kind of rate limiting to our API.</p>\n<p>We can use the <a href=\"https://github.com/tj/node-ratelimiter\">ratelimiter</a> npm package to implement rate limiting. If you are using Express, the <a href=\"https://github.com/nfriedly/express-rate-limit\">express-rate-limit</a> middleware can be used as shown below:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">const RateLimit = require('express-rate-limit');\n\nconst limiter = new RateLimit({\n  windowMs: 15*60*1000, // 15 minutes\n  max: 100, // limit each IP to 100 requests per windowMs\n  delayMs: 0 // disable delaying — full speed until the max limit is reached\n});\n\n// apply to all requests\napp.use(limiter);</code></pre></div>\n<h2>8. Error Handling</h2>\n<p>Any error in the application should be handled gracefully by showing a custom error page to the user instead of showing stack trace in the error page\nthereby leaking sensitive infrastructure information like server info.</p>\n<h2>9. Tools of the trade</h2>\n<p><strong>i) <a href=\"https://github.com/nodesecurity/nsp\">The Node Security Project</a></strong>\nTo check the various npm modules for known vulnerabilities, the Node Security Project provides the nsp tool to check for vulnerabilities:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$ nsp check</code></pre></div>\n<p><strong>ii) <a href=\"https://snyk.io/\">Synk</a></strong>\nSynk checks the application against Snyk’s open source vulnerability database for any known vulnerabilities in our dependencies.</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"language-text\"><code class=\"language-text\">$ npm install -g snyk\n$ cd your-app\n$ snyk test</code></pre></div>\n<p><strong>iii) <a href=\"https://nmap.org/\">nmap</a></strong>\nNmap (“Network Mapper”) is a free and open source utility for network exploration or security auditing.</p>\n<p><strong>iv) <a href=\"http://sqlmap.org/\">sqlmap</a></strong>\nsqlmap is an open source penetration testing tool that automates the process of detecting and exploiting SQL injection flaws and taking over of database servers.</p>\n<p><strong>v) <a href=\"https://portswigger.net/burp\">Burp Suite</a></strong>\nThe must-have tool for application penetration testing. It includes an automated scanner to detect most common vulnerabilities in a web application.</p>\n<h3>Further Readings</h3>\n<p><a href=\"https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project\">OWASP Top 10 Most Critical Web Application Security Risks</a></p>\n<p><a href=\"https://blog.risingstack.com/node-js-security-checklist/\">NodeJS Security Checklist</a></p>","fields":{"slug":"/securing-nodejs-applications/","tags":["nodejs","javascript","security","appsec","infosec"]}}}]}},"pageContext":{"slug":"/categories/Coding","category":"Coding","categories":["Architecture","Coding","DevOps","Engineering","ProjectManagement","QA","Social","TechRadar"]}}