<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Jorgonor</title>
    <description></description>
    <link>https://jorgonor.com/</link>
    <atom:link href="https://jorgonor.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 02 Apr 2025 20:19:08 +0000</pubDate>
    <lastBuildDate>Wed, 02 Apr 2025 20:19:08 +0000</lastBuildDate>
    <generator>Jekyll v4.3.3</generator>
    
    
      <item>
        <title>Power up your integration tests with Mock Server</title>
        <description>&lt;h3 id=&quot;what-is-mock-server&quot;&gt;What is Mock Server?&lt;/h3&gt;

&lt;p&gt;Mock Server is a considerably useful tool when testing integrations against HTTP services. It is especially useful for integration tests.
With Mock Server, it is possible to launch an HTTP server within our test suite and define how it should behave when receiving specific requests from a client application.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.mock-server.com/&quot;&gt;&lt;img src=&quot;/img/posts/mockserver.png&quot; alt=&quot;Mock Server&quot; title=&quot;Mock Server&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, Mock Server is able to verify that the client is making the expected requests when a particular execution flow is being executed.&lt;/p&gt;

&lt;h3 id=&quot;in-what-scenarios-is-mock-server-useful&quot;&gt;In what scenarios is Mock Server useful?&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;API First Development&lt;/strong&gt;: If you are using the API First development methodology, Mock Server can be helpful to quickly have a backend application to integrate without needing any real application developed.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Isolation&lt;/strong&gt;: Integration tests will be completely isolated from a pre-production or integration environment. This brings two additional benefits: it adds reproducibility to our tests and simplifies their setup by removing external dependencies.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Execution Speed&lt;/strong&gt;: Tests will run faster as they do not depend on the network or external services.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;deploying-mock-server-as-a-docker-container&quot;&gt;Deploying Mock Server as a Docker container&lt;/h3&gt;

&lt;p&gt;Mock Server can be deployed as a Java application in a Docker container. This can be achieved with the following docker-compose:&lt;/p&gt;

&lt;div class=&quot;language-docker highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;services:
  mockServer:
    image: mockserver/mockserver:5.14.0
    ports:
      - 12345:1080
    environment:
      MOCKSERVER_WATCH_INITIALIZATION_JSON: &quot;true&quot;
      MOCKSERVER_PROPERTY_FILE: /config/mockserver.properties
      MOCKSERVER_INITIALIZATION_JSON_PATH: /config/initializerJson.json
    volumes:
      - type: bind
        source: .
        target: /config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Running this docker-compose with the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose up&lt;/code&gt; will create a Docker container accessible at the URL &lt;a href=&quot;http://localhost:12345&quot;&gt;http://localhost:12345&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To define the expected behavior of the external HTTP server, there are two preferred options: either use the &lt;a href=&quot;https://www.mock-server.com/mock_server/creating_expectations.html&quot;&gt;Mock Server REST API&lt;/a&gt; or a &lt;a href=&quot;https://www.mock-server.com/mock_server/initializing_expectations.html#expectation_initializer_json&quot;&gt;JSON initialization file&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you are integrating a service and you know the expected responses for specific inputs or want to test specific scenarios, you can define various request matchers, such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Using the &lt;a href=&quot;https://www.mock-server.com/mock_server/creating_expectations.html#request_property_matchers&quot;&gt;HTTP request path&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Using a matcher with the &lt;a href=&quot;https://www.mock-server.com/mock_server/creating_expectations.html#button_match_request_by_body_with_json_exactly&quot;&gt;HTTP request body expecting a JSON&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Using a matcher with the &lt;a href=&quot;https://www.mock-server.com/mock_server/creating_expectations.html#button_match_request_by_regex_body&quot;&gt;HTTP request body matching a regular expression&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;Using a matcher for the &lt;a href=&quot;https://www.mock-server.com/mock_server/creating_expectations.html#request_key_to_multivalue_matchers&quot;&gt;HTTP request headers&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to get into the details, check out &lt;a href=&quot;https://github.com/jorgonor/mockserver-samples/&quot;&gt;this GitHub repository&lt;/a&gt;, which contains an example of Mock Server deployed with Docker.
You can download the repository and deploy it with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;docker-compose up&lt;/code&gt;.
Once the Docker container is ready, access &lt;a href=&quot;http://localhost:12345/mockserver/dashboard&quot;&gt;http://localhost:12345/mockserver/dashboard&lt;/a&gt; to view the created expectations and the state of Mock Server.&lt;/p&gt;

&lt;div style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/img/posts/mockserver-dashboard.png&quot; alt=&quot;MockServer Dashboard&quot; style=&quot;display: block; margin: 0 auto;&quot; /&gt;
  &lt;p style=&quot;text-align: center;&quot;&gt;MockServer Dashboard&lt;/p&gt;
&lt;/div&gt;

&lt;h3 id=&quot;integration-tests-in-java-with-mock-server&quot;&gt;Integration Tests in Java with Mock Server&lt;/h3&gt;

&lt;h3 id=&quot;installation-and-configuration&quot;&gt;Installation and Configuration&lt;/h3&gt;

&lt;p&gt;To start using Mock Server in your Java project, you will need to add the necessary dependencies to your build file.&lt;br /&gt;
If you are using Gradle, add the following lines to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.gradle&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-groovy highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;testImplementation&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;org.mock-server:mockserver-netty:5.11.2&apos;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;testImplementation&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;org.mock-server:mockserver-client-java:5.11.2&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;basic-example&quot;&gt;Basic Example&lt;/h3&gt;

&lt;p&gt;Let’s look at an example use case: a middleware library to a REST API for managing book reservations. The library will have a method to retrieve available books and another method to reserve a book.&lt;br /&gt;
Using Mock Server, we can mock an HTTP server directly from our tests. To initialize it, simply invoke the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ClientAndServer.startClientAndServer(&amp;lt;port&amp;gt;)&lt;/code&gt; method before each test.&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LibraryClientTestImpl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DEFAULT_PORT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8181&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LibraryClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;libraryClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LibraryClientImpl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LibraryClientConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setBaseUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;http://localhost:&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DEFAULT_PORT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

  &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ClientAndServer&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clientAndServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@BeforeEach&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setUp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Start a Mock Server&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clientAndServer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ClientAndServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;startClientAndServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;DEFAULT_PORT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@AfterEach&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;tearDown&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Stop the Mock Server&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clientAndServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testGetBooks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;responseBody&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;[{&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;isbn\&quot;: \&quot;9781593279509\&quot;, &quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;title\&quot;:\&quot;Eloquent Javascript\&quot;, &quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;author\&quot;:\&quot;Marijin Haverbeke\&quot;&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;}, {&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;isbn\&quot;: \&quot;9781801072977\&quot;, &quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;title\&quot;:\&quot;Microservices with Spring Boot and Spring Cloud\&quot;, &quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;author\&quot;:\&quot;Magnus Larsson\&quot; &quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;}, {&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;isbn\&quot;: \&quot;9780596004651\&quot;, &quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;title\&quot;:\&quot;Head First Java\&quot;, &quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; \&quot;author\&quot;:\&quot;Kathy Sierra\&quot;&quot;&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;}]&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Define an expectation for when a client makes a GET request to the /v1/books endpoint&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;clientAndServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;HttpRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withMethod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/v1/books&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;respond&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;HttpResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withStatusCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content-Type&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;application/json&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withBody&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;responseBody&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Trigger the request through the library client to test it&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;libraryClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBooks&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Book&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nc&quot;&gt;Assertions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Verify the first book&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;books&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nc&quot;&gt;Assertions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;9781593279509&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getIsbn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Assertions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Eloquent Javascript&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getTitle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Assertions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Marijin Haverbeke&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;book&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAuthor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Verify the remaining books...&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Verify that Mock Server received the GET /v1/books request exactly once.&lt;/span&gt;

    &lt;span class=&quot;nc&quot;&gt;RequestDefinition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;clientAndServer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;retrieveRecordedRequests&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;HttpRequest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withMethod&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;GET&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withPath&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/v1/books&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    
    &lt;span class=&quot;nc&quot;&gt;Assertions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;assertEquals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;requests&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the test, you can see how an expectation is defined programmatically, similar to how we would create a stub in a unit test.
Once the expectation is configured, the request is executed to retrieve the available books from the API, and the received data is verified against the expected results defined in the stub.&lt;/p&gt;

&lt;p&gt;As an extra step, we also validate that the request was made to Mock Server and that the request was executed only once.&lt;/p&gt;

&lt;h3 id=&quot;get-started-with-mock-server&quot;&gt;Get started with Mock Server&lt;/h3&gt;

&lt;p&gt;Mock Server is a very useful tool for validating scenarios that may occur when integrating with a third-party API.
It is a tool worth considering when an application needs to ensure proper integration with a third-party API, adding quality and coverage to ensure that the contract is fulfilled in every build of the application.&lt;/p&gt;

</description>
        <pubDate>Wed, 02 Apr 2025 06:09:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/java/2025/04/02/power-up-your-tests-with-mock-server.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/java/2025/04/02/power-up-your-tests-with-mock-server.html</guid>
        
        <category>Java</category>
        
        <category>Spring Boot</category>
        
        <category>Docker</category>
        
        <category>Testing</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>java</category>
        
      </item>
    
      <item>
        <title>Test containers with Spring Boot. Persistence layer integration testing</title>
        <description>&lt;p&gt;Nowadays, there is no doubt that the quality of software and its flexibility are directly linked to the ability to verify if it still works after a change, a refactor or a new functionality. Time and effort are dedicated developing automated tests for our applications in order to keep
adapting to changes while making sure our software keeps doing what it was doing before.&lt;/p&gt;

&lt;p&gt;A technology that can help us considerably when verifying that our software works as expected is &lt;a href=&quot;https://testcontainers.com/&quot;&gt;Test containers&lt;/a&gt;. Test containers is an open-source framework that allows us to deploy infrastructure dependencies of our application when running tests, so that we can test the application against real infrastructure dependencies.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://testcontainers.com/&quot;&gt;&lt;img src=&quot;/img/posts/test-containers-slider.png&quot; alt=&quot;Test containers&quot; title=&quot;Test containers&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can deploy relational databases, non-relational databases, messaging brokers as well as any software deployable within a Docker container.
We just need our tests to be able to communicate with a &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; daemon and deploy
the test containers that we have configured in our test code.&lt;/p&gt;

&lt;h3 id=&quot;what-problems-do-test-containers-solve&quot;&gt;¿What problems do Test containers solve?&lt;/h3&gt;

&lt;p&gt;By allowing us to automatically deploy infrastructure dependencies of our application, test containers makes it easier
for us to write integration tests that make sure that the components of our application work correctly on the specific infrastructure.
Without test containers, we would have to manage the instance of this infrastructure dependency externally.
Using a shared external instance introduces problems and limitations when initializing
schemes, fixture data, concurrent test executions by some developers, manual infrastructure deploy and so on.&lt;/p&gt;

&lt;p&gt;With test containers, our tests always start with a new instance dedicated only for that test execution and we do not have
to worry about all these situations.&lt;/p&gt;

&lt;h3 id=&quot;test-containers-in-spring-boot&quot;&gt;Test containers in Spring Boot&lt;/h3&gt;

&lt;p&gt;Let’s put our hands on Test containers! In this article the purpose is going to be to test the persistence layer of a microservice.
The microservice is a simple locations REST API, already used in other website articles such as 
&lt;a href=&quot;/en/blog/java/2024/05/15/java-21-virtual-threads-comparison.html&quot;&gt;Java 21 service with virtual threads performance test&lt;/a&gt;.
The source code is available in the Github repository &lt;a href=&quot;https://github.com/jorgonor/spring-boot-location-api&quot;&gt;Spring Boot Location API&lt;/a&gt;.
In order to start the service it is necessary to have &lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt; installed and a &lt;a href=&quot;https://www.oracle.com/es/java/technologies/downloads/#java21&quot;&gt;Java 21 JDK&lt;/a&gt; or higher.&lt;/p&gt;

&lt;p&gt;The idea of this exercise is to prove that the application is able to use PostgreSQL and MongoDB as its persistence engine. Let’s start with PostgreSQL.&lt;/p&gt;

&lt;h4 id=&quot;adding-the-postgresql-infrastructure-tests&quot;&gt;Adding the PostgreSQL infrastructure tests&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-gradle&quot; data-lang=&quot;gradle&quot;&gt;&lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;springBootVersion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;3.2.8&apos;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;springDependencyManagementVersion&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;1.1.4&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plugins&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;java&apos;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;org.springframework.boot&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;${springBootVersion}&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;io.spring.dependency-management&apos;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;${springDependencyManagementVersion}&quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;dependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Other dependencies...
&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;testImplementation&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;org.springframework.boot:spring-boot-testcontainers&apos;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;testImplementation&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;org.testcontainers:postgresql&apos;&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Adding all these dependencies to our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build.gradle&lt;/code&gt; file we are adding the module to use test containers in Spring Boot and also the test container module
to be able to support PostgreSQL test containers.
The next step is going to be configuring the docker image we need to use in our test container. In order to use it in our Spring Boot tests it is going
to be necessary to initialize it as a Spring bean.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@TestConfiguration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxyBeanMethods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LocationApiTestContainersConfiguration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Bean&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@ServiceConnection&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;PostgreSQLContainer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;?&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;postgresqlContainer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PostgreSQLContainer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;DockerImageName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;parse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;postgres:16-alpine&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withUrlParam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;binaryTransfer&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;withUrlParam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;rewriteBatchedInserts&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;true&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ...
&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ServiceConnection&lt;/code&gt; annotation, Spring is going to configure the connection details against the deployed docker container. Now that our
tests are able to start a PostgreSQL instance, it is already possible to write the infrastructure integration tests.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersistenceIntegrationTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Autowired&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;LocationRepository&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locationRepository&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;testLocationDoesNotExist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;LocationId&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locationId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LocationId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;Assertions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;assertThatThrownBy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;locationRepository&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locationId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isInstanceOf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;EntityNotFoundException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// ...
&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The design pattern &lt;em&gt;Template method test pattern&lt;/em&gt; has been chosen in order to be able to reuse our tests for each of the supported persistence engines.
The abstract class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PersistenceIntegrationTest&lt;/code&gt; is going to be used as a test template some test classes implementations may extend.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Import&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;LocationApiTestContainersConfiguration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@ActiveProfiles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;postgres&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@SpringBootTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TestLocationApiApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@Rollback&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PostgresIntegrationTest&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersistenceIntegrationTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PostgresIntegrationTest&lt;/code&gt; inherits the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PersistenceIntegrationTest&lt;/code&gt; test methods and enables the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;postgres&lt;/code&gt; Spring profile. This profile is
going to be the one used in the application to activate the PostgreSQL persistence and it will also initialize the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocationRepository&lt;/code&gt; implementation
responsible for persisting our domain objects into the PostgreSQL RDBMS.&lt;/p&gt;

&lt;h4 id=&quot;adding-the-mongodb-infrastructure-tests&quot;&gt;Adding the MongoDB infrastructure tests&lt;/h4&gt;

&lt;p&gt;The first step is to add the required modules for the mongo test container.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-gradle&quot; data-lang=&quot;gradle&quot;&gt;&lt;span class=&quot;k&quot;&gt;dependencies&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Other dependencies...
&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;testImplementation&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;org.testcontainers:mongodb&apos;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And the required bean to start the mongo test container.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@TestConfiguration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;proxyBeanMethods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LocationApiTestContainersConfiguration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...
&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Profile&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mongo&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Bean&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@ServiceConnection&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;MongoDBContainer&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mongoContainer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MongoDBContainer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mongo:6.0.16&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As the last step, another inheritor class of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PersistenceIntegrationTest&lt;/code&gt; is created in order to execute the MongoDB infrastructure integration tests.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;nd&quot;&gt;@Import&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;LocationApiTestContainersConfiguration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@ActiveProfiles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;mongo&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@SpringBootTest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;classes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;TestLocationApiApplication&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MongoIntegrationTest&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersistenceIntegrationTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;At this point a project framework has been created in order to use a CI environment that guarantees in each build that our application
still works against both database engines and also the exact docker image version of the database that we are using in our production environments.&lt;/p&gt;

&lt;h3 id=&quot;test-containers-and-github-actions&quot;&gt;Test containers and Github Actions&lt;/h3&gt;

&lt;p&gt;Closing the article, I wanted to remark the use of &lt;a href=&quot;https://github.com/features/actions&quot;&gt;Github Actions&lt;/a&gt; as a simple and available CI engine.
In the &lt;a href=&quot;https://github.com/jorgonor/spring-boot-location-api/actions&quot;&gt;example repository&lt;/a&gt; it can be checked that Github Actions builds the
artifact with Gradle, executing the tests with test containers as a build requirement.&lt;/p&gt;
</description>
        <pubDate>Sun, 28 Jul 2024 10:30:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/java/2024/07/28/test-containers-with-spring-boot.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/java/2024/07/28/test-containers-with-spring-boot.html</guid>
        
        <category>Java</category>
        
        <category>Spring Boot</category>
        
        <category>Docker</category>
        
        <category>Testing</category>
        
        <category>PostgreSQL</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>java</category>
        
      </item>
    
      <item>
        <title>Java 21 service with virtual threads performance test</title>
        <description>&lt;p&gt;I’m back to share the results of a comparison I was curious about: comparing the scalability of a simple microservice developed with Spring Boot. The idea behind this exercise is to test how &lt;a href=&quot;https://spring.io/blog/2022/10/11/embracing-virtual-threads&quot;&gt;Virtual Threads&lt;/a&gt; (one of the most famous Java 21 new features) impact on service availability.&lt;/p&gt;

&lt;p&gt;The service will be responsible for providing a simple REST API to store, read, modify, and delete locations in a PostgreSQL database. The code is available in the GitHub repository &lt;a href=&quot;https://github.com/jorgonor/spring-boot-location-api&quot;&gt;spring-boot-location-api&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to develop this microservice I’ve used the traditional technological stack of Spring Boot, with the &lt;a href=&quot;https://docs.spring.io/spring-boot/docs/current/reference/html/web.html&quot;&gt;Spring Web&lt;/a&gt; and &lt;a href=&quot;https://spring.io/projects/spring-data-jdbc&quot;&gt;Spring Data JDBC&lt;/a&gt; starters. To the most curious, in the repository branch &lt;a href=&quot;https://github.com/jorgonor/spring-boot-location-api/tree/webflux-r2dbc&quot;&gt;webflux-r2dbc&lt;/a&gt; I’ve also added an equivalent reactive implementation using &lt;a href=&quot;https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.reactive&quot;&gt;Spring Webflux&lt;/a&gt;
and &lt;a href=&quot;https://spring.io/projects/spring-data-r2dbc&quot;&gt;Spring Data R2DBC&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;how-to-execute-the-load-tests&quot;&gt;How to execute the load tests&lt;/h3&gt;

&lt;p&gt;To measure the availability with and without virtual threads, I will use the command-line program &lt;a href=&quot;https://linux.die.net/man/1/siege&quot;&gt;siege&lt;/a&gt;, which provides a straightforward interface for executing load tests. Let’s take a look at an example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;siege &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; 1200 &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; 60s http://127.0.0.1:8080/location/1&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This command will launch 1,200 concurrent HTTP requests (&lt;em&gt;using the -c option&lt;/em&gt;) against the specified endpoint for 60 seconds (&lt;em&gt;using the -t option&lt;/em&gt;). With this command, the availability of the endpoint that responds to GET requests can be measured with the different microservice configurations.&lt;/p&gt;

&lt;h3 id=&quot;virtual-threads-and-blocking-services&quot;&gt;Virtual threads and blocking services&lt;/h3&gt;

&lt;p&gt;Let’s check the benefits of using Virtual Threads in a traditional blocking application. Traditional blocking applications typically use a thread to handle each incoming request. By default, the JVM uses an operating system thread to handle these HTTP requests. By enabling Virtual Threads, the Java machine will scale better in scenarios where multiple threads are blocked by I/O operations, as Virtual Threads are specifically optimized for such workloads and do not require the same resources as an OS thread.&lt;/p&gt;

&lt;p&gt;In Spring Boot applications, we can activate Virtual Threads simply by adding the property:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spring.threads.virtual.enabled=true&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;comparing-the-http-get-method&quot;&gt;Comparing the HTTP GET method&lt;/h3&gt;

&lt;p&gt;Let’s see what the results of our location API are with and without Virtual Threads by sending a request that will execute a query against the database.&lt;/p&gt;

&lt;h4 id=&quot;test-with-virtual-threads-disabled&quot;&gt;Test with Virtual Threads disabled&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;53754&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;availability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;98.75&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;data_transferred&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;8.61&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;response_time&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;transaction_rate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;901.61&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;throughput&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                           &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;concurrency&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;989.58&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;successful_transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;             &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;53764&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;failed_transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;681&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;longest_transaction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;31.17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;shortest_transaction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.00&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;test-with-virtual-threads-enabled&quot;&gt;Test with Virtual Threads enabled&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60490&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;availability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;99.24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;data_transferred&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;9.69&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;response_time&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.99&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;transaction_rate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                  &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1011.20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;concurrency&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;998.96&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;successful_transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;             &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60509&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;failed_transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;465&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;longest_transaction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;12.33&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;shortest_transaction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.00&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                                                    &lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The availability provided by the solution with virtual threads is superior.
Additionally, &lt;strong&gt;it is capable of handling 13% more requests within the same time interval&lt;/strong&gt; without any changes to our code, resulting in significantly improved scalability.&lt;/p&gt;

&lt;h3 id=&quot;comparing-the-http-post-method&quot;&gt;Comparing the HTTP POST method&lt;/h3&gt;

&lt;p&gt;Now let’s examine the performance of the location persistence endpoint. This test has consistently been conducted with an empty table to ensure equal conditions between executions with and without virtual threads.&lt;/p&gt;

&lt;h4 id=&quot;test-with-virtual-threads-disnabled&quot;&gt;Test with Virtual Threads disnabled&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;   
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;45858&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;availability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;98.29&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;data_transferred&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;5.51&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;response_time&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;transaction_rate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;772.28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;concurrency&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;988.10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;successful_transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;             &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;45885&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;failed_transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;800&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;longest_transaction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;11.32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;shortest_transaction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.00&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;test-with-virtual-threads-enabled-1&quot;&gt;Test with Virtual Threads enabled&lt;/h4&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;53267&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;availability&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;99.28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;data_transferred&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                     &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;6.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;response_time&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;transaction_rate&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;894.79&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;concurrency&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                        &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;996.25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;successful_transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;             &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;53277&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;failed_transactions&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                   &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;385&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;longest_transaction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;35.83&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;shortest_transaction&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;                 &lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.00&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In this case &lt;strong&gt;the service availability provided by the virtual threads solution is also better, being able to respond to 16% more requests&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;summing-up&quot;&gt;Summing up&lt;/h3&gt;

&lt;p&gt;Definitely, virtual threads offer performance advantages for our blocking Java services. If your projects are already using Java 21 or migrating those that receive heavier loads to this version do not require a significant effort, it could be a good idea to consider starting to use virtual threads in your Java services as soon as possible.&lt;/p&gt;
</description>
        <pubDate>Wed, 15 May 2024 15:00:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/java/2024/05/15/java-21-virtual-threads-comparison.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/java/2024/05/15/java-21-virtual-threads-comparison.html</guid>
        
        <category>Java</category>
        
        <category>JDBC</category>
        
        <category>Tomcat</category>
        
        <category>Spring Boot</category>
        
        <category>PostgreSQL</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>java</category>
        
      </item>
    
      <item>
        <title>How to log SQL queries using Entity Framework 6 like in EF Core</title>
        <description>&lt;p&gt;Watching the SQL queries Entity Framework executes is quite useful when a slow
query needs optimization. If you’re already using ASP.NET Core, you might have already noticed
that the debugging stream already outputs these SQL queries for you. But, if you’re working
with ASP.NET MVC or ASP.NET Web API projects, by default you won’t see the SQL queries executed by EF.&lt;/p&gt;

&lt;p&gt;Even though, there’s a very simple trick to be able to see the actual SQL.
Simply add the following code in your &lt;em&gt;DbContext&lt;/em&gt; constructor.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/jorgonor/e9cd3db5e2fe480332c33508a0be0d18.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;Once this piece of code has been added, you will be able to see the SQL queries your code executes
in the Output tab. Have a look at the screenshot below.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col s12&quot;&gt;
        &lt;img src=&quot;/img/posts/ef6-sql-query-debugging.png&quot; class=&quot;img-responsive img-center&quot; alt=&quot;EF6 Context SQL query debugging&quot; /&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;With the output generated by the &lt;em&gt;Debugger.Log&lt;/em&gt; method it’s possible to find out slow queries. A good
idea would be even to generate a neat report from these messages. However, for quick and dirty debugging,
this trick works.&lt;/p&gt;
</description>
        <pubDate>Mon, 29 May 2017 20:00:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/aspnet/2017/05/29/entity-framework-6-dbcontext.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/aspnet/2017/05/29/entity-framework-6-dbcontext.html</guid>
        
        <category>Entity Framework</category>
        
        <category>ASP.NET</category>
        
        <category>EF Core</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>aspnet</category>
        
      </item>
    
      <item>
        <title>Why properties are evil in C#</title>
        <description>&lt;p&gt;As many of you might already know, properties are a neat way to define getters and setters. Many languages, such as C#, Delphi, Javascript or PHP support them
and they are first-class citizens in the .NET ecosystem. Although properties are a handy resource, some property implementations can turn out to be evil.
Very evil. Let’s dive into them.&lt;/p&gt;

&lt;h3 id=&quot;side-effects-in-property-code&quot;&gt;Side-effects in property code&lt;/h3&gt;

&lt;p&gt;Causing side-effects is the worst practice when using properties, and it’s more spread than it seems at first. What can we consider side-effects?
Modifying a nested object state, making a database query that modifies database state or change values in other fields that have nothing
to do with the actual Property are side-effects examples. Properties are an abstraction to fields, so noone will expect that when I get a value in a property,
other values change. This principle is also applicable to getters and setters in languages where properties are not available.&lt;/p&gt;

&lt;h3 id=&quot;slow-properties&quot;&gt;Slow properties&lt;/h3&gt;

&lt;p&gt;Properties are an abstraction to fields and fields are expected to be as fast as reading/writing a memory address.
If you are reviewing why your code is slow, you are not going to expect a property is the responsible at first.
Use methods instead of properties for slow methods, even better if you can make these methods async if I/O is involved.&lt;/p&gt;

&lt;h3 id=&quot;properties-as-method-arguments&quot;&gt;Properties as method arguments&lt;/h3&gt;

&lt;p&gt;Some APIs, use properties as method arguments. Imagine a ZIP compressor that works like this.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ZIPCompressor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InputFiles&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar.odt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;baz.png&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OutputFile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;file.zip&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Compress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;em&gt;InputFiles&lt;/em&gt; and &lt;em&gt;OutputFile&lt;/em&gt; are not natural &lt;em&gt;ZipCompressor&lt;/em&gt; properties, they look more like &lt;em&gt;Compress&lt;/em&gt; method arguments.
Wouldn’t it be cleaner if instead of properties, regular method arguments were used?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ZIPCompressor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputFiles&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar.odt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;baz.png&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputFile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;file.zip&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Compress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inputFiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This code smell can be found with methods that would need several arguments because of high configuration.
In these cases it’s better to define a value object that would have the default arguments already set.
We could simply instantiate it and set the properties we need to customize the configuration to our needs.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ZIPCompressor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;zipCompressionSettings&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ZIPCompressionSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;zipCompressionSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InputFiles&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;foo.txt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;bar.odt&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;baz.png&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;zipCompressionSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OutputFile&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;file.zip&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Compress&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zipCompressionSettings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This way code is far cleaner. Code is not going to mislead the reader to think that the code is mutating the &lt;em&gt;ZIPCompressor&lt;/em&gt; object and
the API user would not have to remember to reset all these properties in future calls to the &lt;em&gt;Compress&lt;/em&gt; method.&lt;/p&gt;

&lt;h2 id=&quot;when-to-use-properties-then&quot;&gt;When to use properties then?&lt;/h2&gt;

&lt;p&gt;Rule of thumb, use them as getters and setters. Just that. Some other legitimate cases would be caching
values or making helper methods to object attributes. For example, calculate the Age from the BirthDate.
The best advice is to keep always in mind that &lt;strong&gt;properties are an abstraction to fields&lt;/strong&gt;. Keep that in mind
when writing your properties and WTFs will decrease in your codebase.&lt;/p&gt;
</description>
        <pubDate>Sat, 04 Feb 2017 16:30:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/aspnet/2017/02/04/why-properties-are-evil.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/aspnet/2017/02/04/why-properties-are-evil.html</guid>
        
        <category>Properties</category>
        
        <category>.NET</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>aspnet</category>
        
      </item>
    
      <item>
        <title>Entity Framework 6 and &quot;There is already an open DataReader&quot;</title>
        <description>&lt;p&gt;Entity Framework is an amazing ORM. It has differences with other ORMs like Hibernate or Doctrine, but
at the same time feels more comfortable. Two key differences with other ORMs are LINQ as its query language
(LINQ it’s a compiled language, if you like to rename stuff you know how many errors this feature can prevent)
and being able to use foreign key values without having to join with the related entity.&lt;/p&gt;

&lt;p&gt;But, it has a &lt;strong&gt;poor proxy pattern&lt;/strong&gt;. Navigation properties, the Entity Framework name for relationships between entities,
can be accessed with lazy loading like in other ORMs, but in Entity Framework you must load the entire result set in a list
before traversing it or an exception will show up saying “There is already an open DataReader associated with this Connection”.
This happens because Entity Framework attempts to start a new data reader while it is already reading the data
reader for the previous collection.&lt;/p&gt;

&lt;p&gt;While it’s not a big deal when you have an upfront database design that won’t ever change,
this usually breaks code when a new relationship is added to an entity that already exists if you
need to use this new relationship in data transfer objects or in every place where you are retrieving
data from this entity.
So, what can we do to make our codebase more reliable and prevent production errors? SQL Server has a feature called
&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/ms131686.aspx&quot;&gt;Multiple Active Result Sets (MARS)&lt;/a&gt;.
This feature allows the client code to open more than one DataReader at the same time.
It clearly fixes it, while I don’t recommend using it in development because this error is actually telling us that we are probably
doing something wrong. In development, this exception can help you to prevent performance problems lead by lazy loading
with big datasets. When retrieving data from a navigation property, there is a 99% chance that what you actually wanted to do was
to load your data eagerly. So, if you don’t have MARS enabled in Debug Mode, these issues will show up with the
so-called exception. But if you don’t want your production code to fail unexpectedly after a database update,
then enable MARS only in Release. The only needed change is to change your Connection String like this.&lt;/p&gt;

&lt;pre&gt;
Data Source=MSSQL; Initial Catalog=AdventureWorks; Integrated Security=SSPI; MultipleActiveResultSets=True
&lt;/pre&gt;

&lt;p&gt;Hope this helps!&lt;/p&gt;
</description>
        <pubDate>Sat, 06 Aug 2016 16:30:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/aspnet/2016/08/06/entity-framework-6-there-is-already-an-open-data-reader.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/aspnet/2016/08/06/entity-framework-6-there-is-already-an-open-data-reader.html</guid>
        
        <category>C#</category>
        
        <category>.NET</category>
        
        <category>ASP.NET</category>
        
        <category>Entity Framework</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>aspnet</category>
        
      </item>
    
      <item>
        <title>ETagFilePathResult, an ActionResult to save bandwidth in ASP.NET MVC.</title>
        <description>&lt;p&gt;&lt;a href=&quot;http://www.asp.net/mvc&quot;&gt;ASP.NET MVC&lt;/a&gt; provides several ways to serve files from controllers,
but all of them require to serve the entire file content through the network, something that
will make our website slow and more expensive while it’s ridiculous to transfer the same content
over the network every time the resource is requested.
Client-side HTTP caching can easily prevent downloading all those extra bytes. In this post
we offer a solution to it without doing any complicated stuff,
using the ActionResult abstract class to integrate a solution based on &lt;a href=&quot;https://en.wikipedia.org/wiki/HTTP_ETag&quot;&gt;ETags&lt;/a&gt;
in ASP.NET MVC to implement the client-side caching.&lt;/p&gt;

&lt;h3 id=&quot;why-do-i-need-to-return-static-files-from-a-controller&quot;&gt;Why do I need to return static files from a controller?&lt;/h3&gt;

&lt;p&gt;It might seem ridiculous to return static files from a controller. Well, &lt;strong&gt;it is not&lt;/strong&gt;. In several
scenarios it is very useful and secures your web application.
For instance, when there are private resources that might be readable only for a subset of users
you &lt;strong&gt;must&lt;/strong&gt; validate in the controller if the resource is readable for the user who requests it,
if not you’re creating a security hole by mistake.
Other use cases are dynamically generated files backed by a
server-side cache, or even customized stylesheets backed on a server file too.&lt;/p&gt;

&lt;h3 id=&quot;alright-but-let-me-see-the-code&quot;&gt;Alright, but let me see the code!&lt;/h3&gt;

&lt;p&gt;This class is analogous to other classes that are already in ASP.NET MVC like
&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/system.web.mvc.filepathresult(v=vs.118).aspx&quot;&gt;FilePathResult&lt;/a&gt; or
&lt;a href=&quot;https://msdn.microsoft.com/en-us/library/system.web.mvc.filestreamresult(v=vs.118).aspx&quot;&gt;FileStreamResult&lt;/a&gt;.
While these classes work, they do not implement any client-side caching mechanism.
So, with &lt;em&gt;ETagFilePathResult&lt;/em&gt; an ETag will be calculated from the server file full path and the file last write time and returned
to the client, letting the client know that the resource can be cached and indexed by this ETag.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ActionResult&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Find the image that matches with the incoming id.&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ETagFilePathResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;imagePath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;If-None-Match&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ETagFilePathResult&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ActionResult&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;previousETag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uniqueSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ETagFilePathResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;previousETag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uniqueSource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;contentType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;previousETag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;previousETag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uniqueSource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uniqueSource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ExecuteResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ControllerContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ArgumentNullException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;context&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;HttpResponseBase&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ContentType&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;contentType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;FileInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileInfo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FileInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eTag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CalculateETag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Content-Length&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetCacheability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HttpCacheability&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ServerAndPrivate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetETag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eTag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eTag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;previousETag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StatusCode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HttpStatusCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NotModified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;TransmitFile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;virtual&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CalculateETag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FileInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;            
        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hashSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bContentsToHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;hashSource&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;fileInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;fileInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LastWriteTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;uniqueSource&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;bContentsToHash&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Unicode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hashSource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;hash&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HashAlgorithm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CryptoConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateFromName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;MD5&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
                                            &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ComputeHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bContentsToHash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eTag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BitConverter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Replace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                                  &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToLower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;eTag&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The next time the browser asks for this resource, it will add an If-None-Match header with the ETag,
and the server will check if that ETag matches the current file stored in the filesystem. If it does, it returns only an HTTP
&lt;a href=&quot;https://httpstatuses.com/304&quot;&gt;Not Modified&lt;/a&gt; status code, and doesn’t transmit the file content to the client, authorizing the browser
to keep using the same copy it downloaded previously for this resource.
Isn’t it cool? And no extra code needed in your controller!&lt;/p&gt;

&lt;p&gt;Given this code, it is pretty straightforward to implement alternatives,
such as an ActionResult that serves a file from a stream or a byte array
and &lt;em&gt;etags&lt;/em&gt; it. In this case we would not be able to use the last write time,
but we could simply hash the content of the stream and calculate the ETag
from that.&lt;/p&gt;

&lt;p&gt;I hope this helps and if you implement any alternative don’t hesitate to share in comments!&lt;/p&gt;
</description>
        <pubDate>Mon, 04 Jul 2016 21:00:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/aspnet/2016/07/04/etagfilepathresult-actionresult-save-bandwidth-aspnet-mvc.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/aspnet/2016/07/04/etagfilepathresult-actionresult-save-bandwidth-aspnet-mvc.html</guid>
        
        <category>C#</category>
        
        <category>.NET</category>
        
        <category>ASP.NET</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>aspnet</category>
        
      </item>
    
      <item>
        <title>Nativescript. The native alternative to Ionic.</title>
        <description>&lt;p&gt;If we had to pick an emerging and changing field in technology throughout development today, Mobile application development
would be the most accurate choice. Tools and frameworks in this field are more exposed to bigger changes. That is why,
new hybrid mobile app frameworks are emerging again and one of these new frameworks is &lt;a href=&quot;https://www.nativescript.org/&quot;&gt;&lt;strong&gt;Nativescript&lt;/strong&gt;&lt;/a&gt;.
&lt;a href=&quot;https://www.nativescript.org/&quot;&gt;&lt;strong&gt;Nativescript&lt;/strong&gt;&lt;/a&gt; is a new open-source technology by 
&lt;a href=&quot;http://www.telerik.com/&quot;&gt;&lt;strong&gt;Telerik&lt;/strong&gt;&lt;/a&gt; that enables developing native apps using Javascript or Typescript,
that can run on Android, iOS and, in the near future, Windows, with the Windows Universal Apps flavour.
This native feature is what puts the &lt;em&gt;de facto&lt;/em&gt; hybrid mobile app framework &lt;a href=&quot;http://ionicframework.com/&quot;&gt;&lt;strong&gt;Ionic&lt;/strong&gt;&lt;/a&gt; in peril,
making it possible to be replaced by &lt;a href=&quot;https://www.nativescript.org/&quot;&gt;&lt;strong&gt;Nativescript&lt;/strong&gt;&lt;/a&gt;, a more performant alternative.&lt;/p&gt;

&lt;h3 id=&quot;how-native-is-nativescript&quot;&gt;How &lt;em&gt;native&lt;/em&gt; is Nativescript?&lt;/h3&gt;

&lt;p&gt;I guess you’re surprised that &lt;strong&gt;Nativescript&lt;/strong&gt; supports developing native mobile apps using Javascript as the programming language, using also
a subset of CSS for UI customization and XML for component view definition and layouts. This new
technology uses the native UI components in the mobile platform where the app runs, making the user
experience faster, smoother and more familiar. Invoking native platform methods is also possible,
and you don’t have to use a different language, you can simply use them from Javascript.
This feature is amazing, allowing you to use the good native things while you use Javascript as the glue-code
to put everything together and leave heavy-weight operations and UI to the device native APIs. But, how does this work?
To make this possible, Nativescript uses different Javascript engines depending on the platform, and expose
Javascript objects with the native APIs, calling native APIs like if they were just methods and objects in Javascript.
A thorough explanation is available &lt;a href=&quot;http://developer.telerik.com/featured/nativescript-works/&quot;&gt;in this post&lt;/a&gt;
focusing on the Javascript/Native bridge mechanism. Also, a less extense but maybe easier explanation can be
found in the next video.&lt;/p&gt;

&lt;iframe width=&quot;100%&quot; height=&quot;480&quot; src=&quot;https://www.youtube.com/embed/I3_ZnWTj-NA&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h3 id=&quot;community-and-plugins&quot;&gt;Community and plugins&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Nativescript&lt;/strong&gt; community is growing day by day. A &lt;a href=&quot;http://developer.telerik.com/wp-login.php?action=slack-invitation&quot;&gt;Slack channel&lt;/a&gt; 
is available and they are also putting some effort in the project internationalization.&lt;/p&gt;

&lt;p&gt;Many plugins have already been developed to be able to use native components in Nativescript,
and there is also an official marketplace of plugins called the &lt;a href=&quot;https://plugins.telerik.com/nativescript&quot;&gt;Telerik Verified Plugins Marketplace&lt;/a&gt;
Some good examples are, an &lt;a href=&quot;https://plugins.telerik.com/nativescript/plugin/admob&quot;&gt;Admob&lt;/a&gt; plugin, &lt;a href=&quot;https://plugins.telerik.com/nativescript/plugin/sqlite&quot;&gt;Sqlite&lt;/a&gt;,
&lt;a href=&quot;https://plugins.telerik.com/nativescript/plugin/social-share&quot;&gt;Social Share&lt;/a&gt;
or &lt;a href=&quot;https://plugins.telerik.com/nativescript/plugin/firebase&quot;&gt;Firebase&lt;/a&gt;. 
And, remember, you will always be able to use the native Javascript bridge if you need to invoke native platform methods.&lt;/p&gt;

&lt;p&gt;There are also utilities that make using Nativescript less painful for those who are not used to the terminal.
&lt;strong&gt;Telerik&lt;/strong&gt; is developing a Visual Studio Code extension that can be installed from the &lt;a href=&quot;https://www.nativescript.org/nativescript-for-visual-studio-code&quot;&gt;following link&lt;/a&gt;.
With this extension, you can launch your application from the IDE without having to execute manually the Nativescript commands.&lt;/p&gt;

&lt;h3 id=&quot;is-it-a-mature-technology&quot;&gt;Is it a mature technology?&lt;/h3&gt;

&lt;p&gt;&lt;a href=&quot;https://www.nativescript.org/&quot;&gt;&lt;strong&gt;Nativescript&lt;/strong&gt;&lt;/a&gt; is a new technology and there are still some points where it can be improved.
After having tested the tool, its development workflow could be difficult to the beginner, and there are some execution
options, like livesync, where finding that you have some error in the XML markup might get unnoticed. I guess some of these things
will get improved in future releases.&lt;/p&gt;

&lt;p&gt;Apart from this, a key point is the community. Ionic, the framework that made hybrid-app development mainstream,
has a mature community and it’s still a Javascript framework widely used, so here is a big challenge for the Nativescript
team in order to grow a community around it.&lt;/p&gt;

&lt;h3 id=&quot;native-against-standard&quot;&gt;Native against standard.&lt;/h3&gt;

&lt;p&gt;Ionic is in a tough situation. &lt;a href=&quot;http://blog.ionic.io/announcing-the-release-of-ionic-2-beta-6/&quot;&gt;Ionic’s team is working on Ionic 2&lt;/a&gt;
which will give support to &lt;a href=&quot;https://angular.io/docs/ts/latest/quickstart.html&quot;&gt;Angular.js 2&lt;/a&gt;.
This new framework is a revolution in Frontend development, and it was a must to have it in its version 2, but that has made them lose
steam against technologies like &lt;a href=&quot;https://facebook.github.io/react-native/&quot;&gt;Facebook’s &lt;strong&gt;React Native&lt;/strong&gt;&lt;/a&gt; or &lt;strong&gt;Nativescript&lt;/strong&gt; in things
like performance. Nativescript 2.0 &lt;a href=&quot;https://www.nativescript.org/blog/details/nativescript-2.0---the-best-way-to-build-cross-platform-native-mobile-apps&quot;&gt;also supports Angular.js 2&lt;/a&gt;,
what could be summed up as that Ionic might be less competitive than Nativescript for those developers
who start an app from scratch.&lt;/p&gt;

&lt;p&gt;All in all, hybrid apps framework market is in a revolution (again). There are good prospects for solutions that are closer to native,
while Ionic should consider including some of them in their framework unless these native-UI solutions
are not so valued by developers as they should be.
We’ll see in the near future if &lt;strong&gt;Nativescript&lt;/strong&gt; becomes the reference
in hybrid app development, or &lt;strong&gt;Ionic Framework&lt;/strong&gt; stands still in its current top position.&lt;/p&gt;
</description>
        <pubDate>Fri, 06 May 2016 21:00:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/javascript/2016/05/06/nativescript-native-alternative-to-ionic.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/javascript/2016/05/06/nativescript-native-alternative-to-ionic.html</guid>
        
        <category>javascript</category>
        
        <category>app</category>
        
        <category>mobile</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>javascript</category>
        
      </item>
    
      <item>
        <title>Ilmerge. The target assembly lists itself as an external reference</title>
        <description>&lt;p&gt;I’ve made my mind to do this post just because I saw there wasn’t a solution to what happened to me with this problem, even though the solution to it was pretty naive to me.
The thing is, in an ASP.NET project, I have a publish profile with precompilation enabled and with the advanced precompile option “Merge all outputs to a single assembly” enabled too.
I decided to set to this output assembly my project name, something that seemed to me the right thing to do. But then, suddenly a misterious error showed up.&lt;/p&gt;
&lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col s12&quot;&gt;
        &lt;img alt=&quot;Publish Profile&quot; class=&quot;responsive-img&quot; src=&quot;/img/posts/publish_profile.png&quot; /&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;An error occurred when merging assemblies: ILMerge.Merge: The target assembly ‘Whatever’ lists itself as an external reference&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col s12&quot;&gt;
        &lt;img alt=&quot;ILMerge error&quot; class=&quot;responsive-img&quot; src=&quot;/img/posts/ilmerge_errorlist.png&quot; /&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;I didn’t have a reference to the same project anywhere, what was this error about?
After googling for a while, I decided to do the silliest attempt to solve the issue, that kind of change you don’t think is going to fix it,
but, why not trying? &lt;strong&gt;I changed the output assembly name&lt;/strong&gt;. And the error vanished. And everything worked.
So I had wasted a morning because of something so simple…&lt;/p&gt;

&lt;p&gt;I hope this post now prevents you from losing yours. Please try it out, because &lt;strong&gt;in my case it worked!&lt;/strong&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 05 Feb 2016 19:00:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/aspnet/2016/02/05/ilmerge-target-assembly-lists-itself-as-an-external-reference.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/aspnet/2016/02/05/ilmerge-target-assembly-lists-itself-as-an-external-reference.html</guid>
        
        <category>C#</category>
        
        <category>.NET</category>
        
        <category>ASP.NET</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>aspnet</category>
        
      </item>
    
      <item>
        <title>PHP7. The new PHP version is here.</title>
        <description>&lt;p&gt;&lt;strong&gt;PHP7&lt;/strong&gt; is here. Well, the final release hasn’t been released yet, but next 12th November is &lt;a href=&quot;https://wiki.php.net/todo/php70#timetable&quot;&gt;scheduled to be released&lt;/a&gt;
so maybe when you are reading this post the stable final release might be released. And, what does this new language version provide?
The &lt;em&gt;killer feature&lt;/em&gt; promised is &lt;strong&gt;performance&lt;/strong&gt;. Zend has published the next &lt;a href=&quot;http://www.zend.com/en/resources/php-7&quot;&gt;infographic&lt;/a&gt; where you can see
how they announce a &lt;strong&gt;2x performance improvement&lt;/strong&gt;. This might be a half of servers, software twice faster, so it is a considerable
enhancement for the whole PHP ecosystem.&lt;/p&gt;

&lt;h3 id=&quot;performance&quot;&gt;Performance&lt;/h3&gt;

&lt;p&gt;Zend did also publish &lt;a href=&quot;http://www.zend.com/en/resources/php7_infographic&quot;&gt;this infographic&lt;/a&gt; showing the performance boost in PHP frameworks widely used, such as Magento or Drupal.
This infographic shows how PHP7 is capable of serving more requests per second than even HHVM, Facebook’s project to improve PHP performance. At the bottom of the infographic,
it is shown how PHP is the fastest dynamic language resolving Mandelbrot fractals problem. So, we have again another reason to use PHP, &lt;strong&gt;performance&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;new-features&quot;&gt;New features&lt;/h3&gt;

&lt;p&gt;PHP7 also provides new features, that have been added to the language to make it more modern.
Syntactic sugar is always a good thing, that is why we are going to enumerate some of these new features in the language.&lt;/p&gt;

&lt;h4 id=&quot;spaceship-operator&quot;&gt;Spaceship operator&lt;/h4&gt;

&lt;p&gt;In the first place, we are going to explain the weird new feature, the &lt;em&gt;Spaceship operator&lt;/em&gt; (&lt;em&gt;&amp;lt;=&amp;gt;&lt;/em&gt;). This operator
compares values returning what is expected by comparators, -1 if the first operand is less than the second, 0 if both operands are equal
and 1 if the first operador is greater than the second.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This operator is not a huge boost, but it is another weird thing more to the language. The only use case that comes to my mind is to use
it inside anonymous functions used by sorting functions, like &lt;a href=&quot;http://php.net/manual/en/function.usort.php&quot;&gt;usort&lt;/a&gt;.&lt;/p&gt;

&lt;h4 id=&quot;a-language-with-better-typing&quot;&gt;A language with better typing&lt;/h4&gt;

&lt;p&gt;PHP is a dynamic language, but sometimes it is useful to be able to define the type of a function argument or which type a function returns.
In previous PHP versions, only &lt;em&gt;class types&lt;/em&gt; were allowed to be defined in function arguments. PHP7 will allow also scalar types to be hinted in function arguments.
It also adds the possibility to define which type a function returns.
Be ready to have a better autocompletion support for the language in IDEs, because I suppose almost all PHP7 frameworks will make an extensive use of this
new feature.&lt;/p&gt;

&lt;h4 id=&quot;coalesce-operator&quot;&gt;Coalesce operator&lt;/h4&gt;

&lt;p&gt;This flow structure has been the most written piece of code during my professional PHP life.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* $_POST values */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Don’t you agree? Haven’t you ever used this flow structure? To avoid a &lt;em&gt;Notice&lt;/em&gt; when you don’t check if the key exists in an array,
you are forced to write this piece of code. Some developers used the @ operator, that suppresses warnings generated by the statement
surrounded by it. That is not a solution, that was just hiding an error.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* $_POST values */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In PHP7, we will be able to use the coalesce operator that will allow a neater way to solve this problem.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* $_POST values */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;value&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;group-use-declarations&quot;&gt;Group use declarations&lt;/h4&gt;

&lt;p&gt;From PHP5.3 forward, PHP has namespaces. If you use classes from another namespace, the &lt;em&gt;use&lt;/em&gt; statement allows to use simply the class name instead of its full namespace name.
Before PHP7, you had to write a use statement for each class. With PHP7, group use declarations can be used, writing only one line per package making it clearer what classes
and namespaces are being used.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Before&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;some\namespace\ClassA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;some\namespace\ClassB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;some\namespace\ClassC&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AliasClassC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Now&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;use&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;some\namespace\&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ClassA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ClassB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ClassC&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AliasClassC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;integer-division&quot;&gt;Integer division&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;http://php.net/manual/en/function.intdiv.php&quot;&gt;intdiv&lt;/a&gt; function will provide a way to execute the integer division without any trick.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Before&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;floor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Now&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;intdiv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;expressions-in-constants&quot;&gt;Expressions in constants&lt;/h3&gt;

&lt;p&gt;Now, constants will be able to store the result of an expression. Before, PHP threw an exception.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;A&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;DAY_SECONDS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 id=&quot;backwards-compatibility&quot;&gt;Backwards compatibility&lt;/h3&gt;

&lt;p&gt;The biggest of problems with new major language versions, it’s cool to introduce new features and huge improvements but normally these features
introduce &lt;strong&gt;BC breaks&lt;/strong&gt; (backwards compatibility breaks). So, if a project is not under automatic testing or, at least, has a manual procedure
established to know it does what is expected, we have a great problem if we have to migrate it to a newer language major version.&lt;/p&gt;

&lt;p&gt;Regarding PHP7, it has been promised it won’t be a pain to migrate from PHP5 to it. Even though, some changes are worth to take a look before moving on.&lt;/p&gt;

&lt;h4 id=&quot;exception-handling-changes&quot;&gt;Exception handling changes&lt;/h4&gt;

&lt;p&gt;The exception hierarchy has been modified. In PHP7 we will have &lt;a href=&quot;http://php.net/manual/en/class.exception.php&quot;&gt;exceptions&lt;/a&gt; and &lt;a href=&quot;http://php.net/manual/en/class.error.php&quot;&gt;errors&lt;/a&gt;.
Some structures that threw an uncatchable fatal error, now will throw an &lt;em&gt;Error&lt;/em&gt; that could be catched with a try/catch statement, because this &lt;em&gt;Error&lt;/em&gt; class will implement
the &lt;em&gt;Throwable&lt;/em&gt; interface that will be the new way to catch any exception or error in a block of code.&lt;/p&gt;

&lt;p&gt;This will allow catching errors that before stopped the program flow, or simply triggered unmeaningful warnings, like the division by zero.
Now, we can even catch a division by zero error and do something special about it.&lt;/p&gt;

&lt;h4 id=&quot;new-objects-cannot-be-assigned-by-reference&quot;&gt;&lt;em&gt;New&lt;/em&gt; Objects cannot be assigned by reference&lt;/h4&gt;

&lt;p&gt;In PHP7, an object created with a &lt;em&gt;new&lt;/em&gt; statement cannot be assigned by reference in the same statement to a variable.
This piece of code was widely used in previous PHP versions because of some performance reasons, so if you are migrating a legacy project or you’re used to use this 
piece of code in your applications, it’s a good moment to stop using it.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;$a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;\stdClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 id=&quot;more-bc-issues&quot;&gt;More BC issues&lt;/h4&gt;

&lt;p&gt;The explained issues are the most important to me, but you can find other BC issues like removed functions in the &lt;a href=&quot;http://php.net/manual/en/migration70.incompatible.php&quot;&gt;official migration link&lt;/a&gt; or in
&lt;a href=&quot;https://github.com/tpunt/PHP7-Reference#changes&quot;&gt;this Github repository&lt;/a&gt; with examples.&lt;/p&gt;

&lt;h3 id=&quot;php7-is-here-to-make-the-web-better&quot;&gt;PHP7 is here to make the Web better&lt;/h3&gt;

&lt;p&gt;In my opinion, it is a new version with little breaking compatibility changes, something positive, but it this mantra has also made impossible to do more ambitious changes to the language
that might have considerably improved the language. But I suppose PHP mantainers don’t want a Python3 happening in PHP.&lt;/p&gt;

&lt;p&gt;Other features I miss are more types and functions for the PHP internals. A &lt;em&gt;decimal&lt;/em&gt; type would be great to do fixed numeric operations, something basic for high-level languages.
So, to finish with this post, developers must keep updated, so it is important to know which are the new features provided by this new version
because sooner or later this version will become the standard. And the sooner the better. PHP7 has performance and behaviour improvements that can’t be skipped. PHP7 is here to make the Web better.&lt;/p&gt;
</description>
        <pubDate>Tue, 27 Oct 2015 18:00:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/php/2015/10/27/php7-the-new-php-version-is-here.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/php/2015/10/27/php7-the-new-php-version-is-here.html</guid>
        
        <category>PHP</category>
        
        <category>PHP7</category>
        
        <category>Performance</category>
        
        <category>New features</category>
        
        <category>BC</category>
        
        <category>Backward compatibility</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>php</category>
        
      </item>
    
      <item>
        <title>Metabase. A revolutionary reporting tool</title>
        <description>&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://www.metabase.com/&quot;&gt;Metabase&lt;/a&gt;&lt;/strong&gt; is a new open source tool built with Clojure that provides a new way to avoid wasting time on programming your company’s reports.
With a very simple UI, users can configure their own reports and charts by themselves.
Users would be able to retrieve very simple information almost instantly, without having to make a request to the IT team and waiting for them to develop the appropriate report.
As a result, company’s business intelligence process gets considerably improved regarding timing and information feedback.&lt;/p&gt;

&lt;p&gt;Databases can be plugged in Metabase simply by setting the server where the database lives, the database name and its credentials.
A name inside the application that will be visible by users can be set. And it supports &lt;strong&gt;four database engines&lt;/strong&gt;, MySQL, MongoDB, PostgreSQL and H2.&lt;/p&gt;

&lt;h3 id=&quot;how-to-set-it-up&quot;&gt;How to set it up.&lt;/h3&gt;

&lt;p&gt;Metabase can be downloaded from this URL &lt;a href=&quot;http://www.metabase.com/start/&quot;&gt;http://www.metabase.com/start/&lt;/a&gt;.
As I use Linux, I’m going to explain how I have installed it using the “Other platforms” option.&lt;/p&gt;

&lt;p&gt;Simply run&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;java &lt;span class=&quot;nt&quot;&gt;-jar&lt;/span&gt; metabase.jar&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After this step, you can open a browser and open the default Metabase URL &lt;a href=&quot;http://localhost:3000&quot;&gt;http://localhost:3000&lt;/a&gt;. To get started, your personal
information will be asked to set up your user. Apart from that, you can set up the first database or set it up afterwards. For more information on how to set it up
in a production environment &lt;a href=&quot;http://www.metabase.com/docs&quot;&gt;http://www.metabase.com/docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;creating-questions&quot;&gt;Creating questions&lt;/h3&gt;

&lt;p&gt;Simply click on “New Questions”, if you have already set up your database, all the database tables are ready to use.
Metabase uses database metadata to populate the available filters depending on the column type. For example, if the data is “numeric”, it allows
different filters such as “Greater than”, “Less than”, while when a column is a string, these filters are not available.
It is also intelligent to use your schema foreign keys, so you can filter your information also by a related table column!&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col s12&quot;&gt;
        &lt;img alt=&quot;Metabase filters&quot; class=&quot;responsive-img&quot; src=&quot;/img/posts/metabase_filters.png&quot; /&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Questions can be added to the dashboard so that users can analyze information at a glance. And visualization is customizable.
You can choose from many different views that can be used to customize how your users want to see information.&lt;/p&gt;

&lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;col s12&quot;&gt;
        &lt;img alt=&quot;Metabase visualization&quot; class=&quot;responsive-img&quot; src=&quot;/img/posts/metabase_visualization.png&quot; /&gt;
    &lt;/div&gt;
&lt;/div&gt;

&lt;h3 id=&quot;drawbacks&quot;&gt;Drawbacks&lt;/h3&gt;

&lt;p&gt;Unfortunately, as many other JVM solutions, Metabase has a high memory footprint. Without real users load in my personal computer running Linux Metabase is using &lt;strong&gt;about 700 MB&lt;/strong&gt;.
Even though, it’s not a lot when installed on a server and with the amount of work it can save you this shouldn’t put you off of using this awesome open-source solution.&lt;/p&gt;

&lt;h3 id=&quot;lets-use-metabase&quot;&gt;Let’s use metabase!&lt;/h3&gt;

&lt;p&gt;Metabase is a solution that can save your company loads of time and money. Remember that these kind of solutions have a considerable value, and Metabase is
free! Apart from that, if some developers are working on reporting solutions, they will be free to work on other important tasks.
So, if you aren’t using any business intelligence solution, Metabase is a good solution for you.&lt;/p&gt;
</description>
        <pubDate>Sat, 24 Oct 2015 16:30:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/reporting/2015/10/24/metabase.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/reporting/2015/10/24/metabase.html</guid>
        
        <category>Metabase</category>
        
        <category>Reporting</category>
        
        <category>Business Intelligence</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>reporting</category>
        
      </item>
    
      <item>
        <title>Symfony2 is not slow</title>
        <description>&lt;p&gt;If you are working on Web Development you must have read eventually a benchmark. What several times is not that obvious is that the
benchmark you read might not be comparing the different tecchnologies fairly, just because of time and knowledge constraints.
And &lt;strong&gt;Symfony2&lt;/strong&gt; is not an exception, as a framework with several files and features it is always at the lower positions of
the ranking. Even though, &lt;strong&gt;Symfony2 is not slow&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One of the most popular benchmarks on the Internet is the one from &lt;a href=&quot;https://www.techempower.com/benchmarks/&quot;&gt;TechEmpower&lt;/a&gt; that solves
a set of problems with more than a hundred of technologies with an awesome detail. Although, it is still impossible to
be able to develop each solution fairly for such an amount of technologies, programming languages and frameworks.&lt;/p&gt;

&lt;p&gt;Focusing on &lt;strong&gt;Symfony2&lt;/strong&gt;, anybody that has spent more than an evening working with it knows that to put it in a production environment
with a good performance some extra tweaks must be done. But this is just having to change some settings in the configuration files, nothing
to do with the code you’ve developed. As an example, I will show the optimization that has given me better results, an optimization for
the ORM that comes with &lt;strong&gt;Symfony2&lt;/strong&gt;, &lt;em&gt;Doctrine2&lt;/em&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot; data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;na&quot;&gt;doctrine&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;orm&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;metadata_cache_driver&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apc&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;result_cache_driver&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apc&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;query_cache_driver&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;apc&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you can see in the previous example, different sorts of caches can be configured for Doctrine2. The metadata cache
(&lt;em&gt;metadata_cache_driver&lt;/em&gt;) allows that every mapping file between your entities and your database tables can be reused, without the need
to read the file from disk. But the killer setting is &lt;em&gt;query_cache_driver&lt;/em&gt;. When this option is enabled, Doctrine2 only has to transform
a query from DQL to SQL once and, as this forces a compile process behind the scenes, it avoids this work written in PHP in every request.
It will be done once and after that cached. In the real world, when I used this setting for the first time, I noticed that an API endpoint
that was taking a second to finish only took about 50 milliseconds. It was 20x times faster only because I changed a line in a configuration file!!!
About cache engines, Symfony2 offers other cache engines, not only APC like Redis and Memcache.&lt;/p&gt;

&lt;p&gt;And this is just one of the optimizations that can be done. The Internet is full of resources with tutorials and instructions to improve
your Symfony2 application performance critically like &lt;a href=&quot;http://www.slideshare.net/ricardclau/scaling-with-symfony-php-uk&quot;&gt;this one&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Fri, 09 Oct 2015 10:30:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/php/2015/10/09/symfony2-is-not-slow.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/php/2015/10/09/symfony2-is-not-slow.html</guid>
        
        <category>Symfony2</category>
        
        <category>PHP</category>
        
        <category>Performance</category>
        
        <category>Framework</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>php</category>
        
      </item>
    
      <item>
        <title>How to migrate MySQL to MariaDB</title>
        <description>&lt;p&gt;
    As you might already know, MariaDB is the alternative to Oracle MySQL. The MariaDB team mantains two releases right now, one that is compatible with MySQL called MariaDB 5.5
    and a new one for brand new installations, MariaDB 10. We are going to migrate to MariaDB 5.5, which is the recommended for easy migrations without headaches.
&lt;/p&gt;

&lt;p&gt;I have tested this under Ubuntu 14.04. Open a shell, and type/paste the following instructions to do your migration:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;bash
apt-key adv &lt;span class=&quot;nt&quot;&gt;--recv-keys&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--keyserver&lt;/span&gt; keyserver.ubuntu.com 0xcbcb082a1bb943db
apt-get update
apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;mariadb-server&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
    And everything is up and ready. You won&apos;t have to change even your database connection configuration, the applications that were using
    the MySQL driver will keep working perfectly.
&lt;/p&gt;

&lt;p&gt;
    And to finish the post, a warning, &lt;strong&gt;do not test this in live environment unless you have tested it properly!&lt;/strong&gt;
&lt;/p&gt;
</description>
        <pubDate>Sun, 06 Sep 2015 15:00:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/2015/09/06/how-to-migrate-mysql-to-mariadb.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/2015/09/06/how-to-migrate-mysql-to-mariadb.html</guid>
        
        <category>Mysql</category>
        
        <category>MariaDB</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Functional PHP</title>
        <description>&lt;p&gt;
    Functional programming. What is that thing some software gurus talk about? I am going to try to explain it with a basic example in PHP to show you
    how you can use this paradigm for your daily work, demistifying its difficulty in the process. And, yeah, you can use functional programming in PHP, well,
    with a PHP flavour.
&lt;/p&gt;

&lt;h3&gt;What is functional programming?&lt;/h3&gt;

&lt;p&gt;
    The functional programming paradigm is not modern at all. It is based on &lt;a href=&quot;https://en.wikipedia.org/wiki/Lambda_calculus&quot;&gt;Lambda Calculus&lt;/a&gt;.
    One of the first languages that allowed programming using this technique was &lt;a href=&quot;https://en.wikipedia.org/wiki/Lisp_%28programming_language%29&quot;&gt;Lisp&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;Functional programming is all about functions and data structures, there are no objects in there. Pure functional programming languages do not allow mixing
    data with behaviour. But some pieces of this paradigm have been used since the beginning of other languages, like function pointers in C. Usually,
    pure functional languages like Haskell have capabilities that are out of the scope of this post, like &lt;a href=&quot;http://stackoverflow.com/questions/36314/what-is-currying&quot;&gt;Currying&lt;/a&gt;,
    &lt;a href=&quot;https://en.wikipedia.org/wiki/Pattern_matching&quot;&gt;Pattern Matching&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Lazy_initialization&quot;&gt;Lazy Initialization&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
    Given it is usually difficult to understand, we are going to show an example of functional programming using PHP. The example in this post is quite simple,
    and it solves a mundane problem using functional programming, filtering a collection or array.
&lt;/p&gt;

&lt;h3&gt;An example&lt;/h3&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index_and_value_are_even&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;var_export&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;index_and_value_are_even&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
    This code fragment exports an empty array, provided the array values and indices are not even in any element.
&lt;/p&gt;

&lt;p&gt;
    In many applications, pieces of code like these can be found, traversing a collection and applying a filter over it is a common task.
    It is not a bad way to solve the problem, it is simple, standard and easy, but if we solve it like this, we have to write tons of
    syntax that we actually don&apos;t need, repeating the same pattern over and over again and, in real world applications, the problem solved by
    the foreach body isn&apos;t usually just like in the example, it can also be a cumbersome piece of code.
&lt;/p&gt;

&lt;p&gt;
    Let&apos;s see how this function would be implemented using the functional paradigm.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_even&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index_and_value_are_even&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;array_filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_even&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_even&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
    Isn&apos;t this solution much better? It&apos;s obviously a subjective matter but in my opinion the code is more expressive using functional
    programming.
&lt;/p&gt;

&lt;p&gt;
    Even though this piece of code is incorrect. &lt;a href=&quot;http://php.net/manual/en/function.array-filter.php&quot;&gt;array_filter&lt;/a&gt; native function doesn&apos;t
    send the index to the called filter function. This can make this function useless for your needs, more if the array keys have a meaning in your
    application. But, we are programmers, aren&apos;t we? Let&apos;s do our own implementation.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array_filter_with_indices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;callable&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[];&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;foreach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$arr&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$fn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
    Yes, it&apos;s a pretty straightforward implementation. Now we can reuse this filter function applying an anonymous function over it to decide which
    elements fulfill the provided conditions. This implementation also preserves the original indices, not like the native &lt;i&gt;array_filter&lt;/i&gt;.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-php&quot; data-lang=&quot;php&quot;&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;1&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;value1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;abc&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;value3&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
    Another thing of note in this code is that it uses &lt;a href=&quot;http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration&quot;&gt;Type Hinting&lt;/a&gt;,
    a mechanism to check if the function arguments belong to the type the function expects.
    As you can see, it&apos;s possible to type hint an argument as &lt;i&gt;callable&lt;/i&gt;. This kind of &lt;i&gt;type hinting&lt;/i&gt; has been added in version 5.4, so check this before you
    decide to use it in your application.
&lt;/p&gt;

&lt;p&gt;
    I hope you&apos;ve got the gist of this technique. Don&apos;t mind using it in real world applications!!
&lt;/p&gt;
</description>
        <pubDate>Sun, 06 Sep 2015 15:00:00 +0000</pubDate>
        <link>https://jorgonor.com/en/blog/php/2015/09/06/functional-php.html</link>
        <guid isPermaLink="true">https://jorgonor.com/en/blog/php/2015/09/06/functional-php.html</guid>
        
        <category>PHP</category>
        
        <category>Functional programming</category>
        
        
        <category>en</category>
        
        <category>blog</category>
        
        <category>php</category>
        
      </item>
    
  </channel>
</rss>
