Starting with unit testing using Vue.js 2 and Jest

Reading Time: 4 minutes

As a FrontEnd developer, you may know a lot of FrontEnd technologies and frameworks but in time you need to upgrade yourself as a developer. A good skill to strengthen your knowledge is to learn unit testing.

Since I am working with Vue.js for several years, we are going to see some of the basics for testing Vue components using the Jest JavaScript testing framework.

To start, first, we need a Vue.js 2 project created via the Vue CLI. After that we need to add the Jest framework to the project:

# jest unit testing
vue add @vue/unit-jest

I’ll make a simple component that will increase a number on click of a button:

// testComponent.js
export default {
  template: `
    <div>
      <span class="count">{{ count }}</span>
      <button @click="increase">Increase</button>
    </div>
  `,

  data() {
    return {
      count: 0
    }
  },

  methods: {
    increase () {
      this.count++
    }
  }
}

The way of testing is by mounting the components in isolation, after that comes the mocking the needed inputs like injections, props and user events. In the end, comes the confirmation of the outputs of the rendered results emitted events etc.

After that, the components are returned inside a wrapper. A wrapper is an object that contains a mounted component or a VNode and methods to test them.

Let’s create a wrapper using the mount method:

// jestTest.js

// first we import the mount method
import { mount } from '@/vue/test-utils'
import Calculate from './calculate'

// then we mount (wrap) the component
const wrapper = mount(Calculate)

// this way you can access the Vue instance
const vm = wrapper.vm

// you can inspect the wrapper by logging it into the console
console.log(wrapper)

Next step after we do the wrapping, follows to verify if the rendered HTML output of the component matches the expectations.

import { mount } from '@vue/test-utils'
import Calculate from './calculate'

describe('Calculate', () => {
  // Now mount the component and you have the wrapper
  const wrapper = mount(Calculate)

  it('renders the correct markup', () => {
    expect(wrapper.html()).toContain('<span class="calculate">0</span>')
  })

  // it's also easy to check for the existence of elements
  it('has a button', () => {
    expect(wrapper.contains('button')).toBe(true)
  })
})

Then run the tests with npm test and see them pass.

The code in testComponent.js should increment the number on button click so next step is to simulate the user interaction. For this, we need the wrapper’s method wrapper.find() to get the wrapper for the button and then simulate the click event by calling the method trigger().

it('simulation of button click should increment the calculate by 2', () => {
  expect(wrapper.vm.calculate).toBe(0)
  const button = wrapper.find('button')
  button.trigger('click')
  button.trigger('click')
  expect(wrapper.vm.calculate).toBe(2)
})

For asynchronous updates, we use the Vue.nextTick()(need to receive a function as a parameter) method, which comes from Vue. With this method, we are waiting for the DOM update and after that, we execute the code (the code in the function parameter).

// this will not be caught

it('time out', done => {
  Vue.nextTick(() => {
    expect(true).toBe(false)
    done()
  })
})


// the three following tests will work as expected 
// (1)

it('catch the error using done method', done => {
  Vue.config.errorHandler = done
  Vue.nextTick(() => {
    expect(true).toBe(false)
    done()
  })
})

// (2)
it('catch the error using a promise', () => {
  return Vue.nextTick()
    .then(function() {
      expect(true).toBe(false)
    })
})

it('catch the error using async/await', async () => {
  await Vue.nextTick()
  expect(true).toBe(false)
})

Using nextTick can be tricky for the errors because the errors thrown inside it might not be caught by the test runner. That is happening as a consequence of using promises internally. To fix this we can set the done callback as a Vue’s global error handler (1) or we can use the nextTick method without parameter and return it as a promise (2) like we did earlier.

This article is a guide on how to set up the environment and start writing unit tests using Jest. For more information about testing with Vue and using Jest, you can visit the official site for Vue test utils.

JHipster, is it worth it?

Reading Time: 7 minutes

JHipster is an open-source platform to generate, develop and deploy Spring Boot + Angular / React / Vue web applications. And with over 15 000 stars on Github, it is the most popular code generation framework for Spring Boot. But is it worth the hype or is the generated code too difficult to maintain and not production-ready?

How does it work?

The first thing to note is that JHipster is not a separate framework by itself. It uses yeoman and .jdl files in order to generate code in Spring Boot for backend and Angular or React or Vue for frontend. And after the initial generation of the project, you have the option to use the generated code without ever running JHipster commands again or to use JHipster in order to incrementally grow the projects and develop new features.

What exactly is JDL?

JDL is a JHipster-specific domain language where you can describe all your applications, deployments, entities and their relationships in a single file (or more than one) with a user-friendly syntax.

You can use our online JDL-Studio or one of the JHipster IDE plugins/extensions, which support working with JDL files.

Example of simple JDL file for Blog application:

entity Blog {
  name String required minlength(3)
  handle String required minlength(2)
}

entity Post {
  title String required
  content TextBlob required
  date Instant required
}

entity Tag {
  name String required minlength(2)
}

relationship ManyToOne {
  Blog{user(login)} to User
  Post{blog(name)} to Blog
}

relationship ManyToMany {
  Post{tag(name)} to Tag{entry}
}

paginate Post, Tag with infinite-scroll

Which technologies are used?

On the backend we have the following technologies:

  • Spring Boot as the primary backend framework
  • Maven or Gradle for configuration
  • Spring Security as a Security framework
  • Spring MVC REST + Jackson for REST communication
  • Spring Data JPA + Bean Validation for Object Relational Mapping
  • Liquibase for Database updates
  • MySQL, PostgreSQL, Oracle, MsSQL or MariaDB as SQL databases
  • MongoDB, Counchbase or Cassandra as NoSQL databases
  • Thymleaf as a templating engine
  • Optional Elasticsearch support if you want to have search capabilities on top of your database
  • Optional Spring WebSockets for Web Socket communication
  • Optional Kafka support as a publish-subscribe messaging system

On the frontend side these technologies are used:

  • Angular or React or Vue as a primary frontend framework
  • Responsive Web Design with Twitter Bootstrap
  • HTML5 Boilerplate compatible with modern browsers
  • Full internationalization support
  • Installation of new JavaScript libraries with NPM
  • Build, optimization and live reload with Webpack
  • Testing with Jest and Protractor
  • Optional Sass support for CSS design

How to get started?

  1. Pre-requirements: JavaGit and Node.js.
  2. Install JHipster npm install -g generator-jhipster
  3. Create a new directory and go into it mkdir myApp && cd myApp
  4. Run JHipster and follow instructions on the screen jhipster
  5. Model your entities with JDL Studio and download the resulting jhipster-jdl.jh file
  6. Generate your entities with jhipster import-jdl jhipster-jdl.jh
  7. Run ./mvnw to start generated backend
  8. Run npm start to start generated frontend with live reload support

How does the generated code and application look like?

In case you only want to see a sample generated application without starting the whole framework you can check this official Github repo for the latest up-to-date sample code: https://github.com/jhipster/jhipster-sample-app.

Following are some screen from my up and running JHipster application:

Welcome screen jhipster homepageThis is the initial screen when you open your JHipster app

Create a user screenjhipster user create screenWith this form you can create a new user in the app

View all users screenjhipster user management screenIn this screen you have the option to manage all your existing users

Monitoring of your JHipster application screenjhipster monitoring screenMonitoring of JVM metrics, as well as HTTP requests statistics

What are the pros and cons

The important thing to remember is that JHipster is not a “magic bullet” that will solve all your problems and is not an optimal solution for all the new projects. As a good software engineer, you will have to weigh in the pros and cons of this platform and decide when it makes sense to use and when it’s better to go with a different approach. Having used JHipster for production projects these are some of the pros and cons that I’ve experienced:

Pros

  • Easy bootstrap of a new project with a lot of technologies preconfigured
  • JHipster almost always follows best practices and latest trends in backend and frontend development
  • Login, register, management of users and monitoring comes out-of-the-box
  • Wizard for generating your project, only the technologies that you select are included in the project
  • After defining your own JDL file, all of the models, repository, service and controllers classes for your entities are generated, together with integration tests. This is saving a lot of time in the begging of the project when you want to get to feature development as soon as possible

Cons

  • If you are not familiar with technologies that are being used in the generated project it can be overwhelming and it’s easy to get lost into this mix of lots of different technologies
  • Using JHipster after the initial project is not a smooth experience. Classes and Liquibase scripts are being overwritten and you have to be very careful with changing the initial JDL model. Or you can decide to continue without using JHipster after the initial generation of projects
  • REST responses that are returned from endpoints will not always correspond to business requirements, very often you will have to manually modify your initial JHipster REST responses
  • Not all of the options that are available are at the same level, some technologies that JHipster is using and configuring are more polished than the others. Especially true if you decide to use community modules

What kind of projects are a good fit?

Having said all of this, it’s important to understand that there are projects which can benefit a lot from JHipster and projects that are better without using this platform.

In my experience, a good candidate is a greenfield project where it’s expected to deliver a lot of features fast. JHipster will help a lot to be productive from day one and to cut on the boilerplate code that you need to write. So you will be able, to begin with, feature development really fast. This works well with new projects with tight deadlines, proof of concepts, internal projects, hackathons, and startups.

On the other hand, a not so ideal situation is if you have an already started and up and running project, there is not much a JHipster can do in this case. Or another case would if the application has a lot of specific business logic and its not a simple CRUD application, for example, an AI project, a chatbot or a legacy ecosystem where these new technologies are not suitable or supported.

JHipster, is it worth it?

There is only one sure way to decide if JHipster is worth it for your next project or not and that is to try it out yourself and play around with the different features and configuration that JHipster offers.

At best, you will find a new framework for your next project and save a lot of effort next time you have to start a project. At worst, you will get to know the latest trends in both backend and frontend and learn some of the best practices from a very large community.

JavaScript objects: Why? How? Compared with switch-case and if?

Reading Time: 4 minutes

During the development, we use objects and we are always confused which approach is the best. That was the main reason why I decided to write a blog about it, so I really hope in near future most of your obstacles will be resolved and you will be more confident in choosing which is the best approach.

In this blog, I will explain some of the object features and I will make some comparisons, so let’s start!

Switch vs object literals

We all know what is a switch – case statement and we used them at least one time in our life, no matter which programming language. But since we are talking about JavaScript, have you ever asked yourself if it is clever to use it?

Well, of course, the answer is NO. Now you are asking yourself, then it must be if-else statements, but still, the answer is NO. The best approach is to use objects.

Let’s see why…

Problems:

  • switch-case
    • Hard to maintain which leads you to difficult debugging and testing
    • You are manually forced to use break within each case
    • Nested errors
    • Restrictions, like not allowing to use the same constant in two different cases…
    • In JavaScript, everything is based on curly braces, but not switch
    • Evaluates every case until it finds the right one
  • If-else statements
    • Hard to maintain which leads you to difficult debugging and testing
    • Hard to understand when there is complex logic
    • Hard to test
    • Evaluates every statement until it finds the right one if you don’t end it explicitly

According to these problems, the best solution is objects. The reason for that is the advantages that objects are offering us, like:

  • You are not forced to do anything
  • You can use functions inside the objects which means you are much more flexible
  • You can use closure benefits
  • You are using the standard JavaScript objects, which makes the code friendlier
  • Gives you better readability and maintainability
  • Since the objects approach is like a hash table the performance gets better rather than the average cost of switch case
  • All these advantages lead us to the conclusion that objects are more natural and are part of many design patterns in JavaScript where switch-case is an old way of coding

Let’s see an example with objects how they look like:

<!DOCTYPE html>
<html> 
<body>
<script>
      function getById (id) {
            var ids = {
                  'id1': function () {
                        return 'Id 1';
                  },
                  'id2': function () {
                        return 'Id 2';
                  },
                  'default': function () {
                        return 'Default';
                  }
            }
            return (ids[id] || ids['default'])();
      };

      var ref = getById('id1')
      console.log(ref)         // Id 1

      var ref1 = getById()
      console.log(ref)         // Default

      var ref1 = getById(‘noExistingId’)
      console.log(ref)         // Default
</script>
</body>
</html>

hasOwnProperty(key) vs in

hasOwnProperty() – method which returns Boolean or true only if the object contains that property as its own property.

in – operator which returns Boolean or true only if the object contains that property as its own property or in its prototype chain.

function TestObj(){
      this.name = 'TestName';
}
TestObj.prototype.gender = 'male';

var obj = new TestObj();

console.log(obj.hasOwnProperty('name'));       // true
console.log('name' in obj);                    // true
console.log(obj.hasOwnProperty('gender'));     // false 
console.log('gender' in obj);                  // true

Object properties

There are two ways: dot notation and bracket notation. Most of the developers often ask themselves which approach they should use or maybe if there is any difference? In the end, they use one of them wherein most of the cases both solutions work fine without knowing why and without paying attention to its differences. Let’s make an overview.

Dot notation:

  • s can only be alphanumeric, which means it can only include two special characters “_” and “$”
  • Property identifiers can’t start with numbers and variables

Bracket notation:

  • Property identifiers must be String or a variable which references to a String
  • Property identifier can contain any character in their name
var obj = {
      '$test': 'DolarValue',
      '%test': 'PercentageValue'
      …
}

console.log(obj["$test"])                      // 'DolarValue'
console.log(obj.$test)                          // 'DolarValue'

These both will give the same result because both support `$` in their name, but what happens if we use another special character like `%`?

console.log(obj["%test"])    // 'PercentageValue'
console.log(obj.%test)       // It will throw an error:              
                            Uncaught SyntaxError: Unexpected token ‘%’

In the next blog, I will cover loops optimization using the object properties and testing code speed.

The practical guide: Refactor android application to follow the MVP design pattern

Reading Time: 8 minutes

At the beginning of my carrier, I was very lucky to start a few new projects at my company. And every story was a short one and the same: This is going to be the best project ever -> Ops, it got little messy -> Oooops, everything is a mess, there is no going back. So, I realized that it isn’t enough that I can do anything the PO wants, but I have to find the right way of doing it.

I was thinking like: Ok, I will learn unit testing, my code will be tested, and everything will be fine. So, I got into testing, started to read everything about testing, especially unit testing. I started to understand it a little bit, so I decided to write a few unit tests in my existing (mess) projects. I created test classes for some fragment, started to type some test methods, thinking I will figure it out what to test easily, and when I had to type the name of the test method my mind froze.

I had no idea what to test. I started to divide the code into methods, but it wasn’t helping at all. After a ton of research and frustration, I realized that I can’t test anything until I learn some design patterns and/or architectures.

Design patterns and architectures

In theory, there is a small difference between design patterns and architectures. Basically, they are both terms that define the organization of code, but the difference is the layer. Architecture is a more general term of design pattern. There are many design patterns and architectures, and you can’t say for one that it is the best. Today we will look at the MVP design pattern, and we will try to refactor a really bad code into a better one. Hopefully, then, we will try to refactor the better code into an even better one, with clean-like architecture.

Application example

I created an application that fetches some programming quotes, saves them into a room database and displays them into a RecyclerView. If the network calls fail, we display the quotes from the database. It is a common use case, that complicates our lives a little bit. You can check out the no_pattern branch, and run the app.

public class MainActivity extends AppCompatActivity {

    private QuoteDao quoteDao;
    private RecyclerView rvQuotes;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        quoteDao = QuoteDatabase.getQuoteDatabase(this).quoteDao();

        rvQuotes = findViewById(R.id.rvQuotes);
        rvQuotes.setLayoutManager(new LinearLayoutManager(this));

        QuotesApi quotesApi = RetrofitClient.getRetrofit().create(QuotesApi.class);
        Call<List<Quote>> quotesCall = quotesApi.getQuotes();
        quotesCall.enqueue(new Callback<List<Quote>>() {
            @Override
            public void onResponse(Call<List<Quote>> call, Response<List<Quote>> response) {
                if (response.isSuccessful()) {

                    new Thread(() -> quoteDao.insertQuotes(response.body())).start();

                    QuotesAdapter adapter = new QuotesAdapter(response.body());
                    rvQuotes.setAdapter(adapter);
                }
            }

            @Override
            public void onFailure(Call<List<Quote>> call, Throwable t) {
                DatabaseQuotesAsyncTask asyncTask = new DatabaseQuotesAsyncTask(quoteDao, rvQuotes);
                asyncTask.execute();
            }
        });
    }

    static class DatabaseQuotesAsyncTask extends AsyncTask<Void, Void, List<Quote>> {

        private QuoteDao quoteDao;
        private WeakReference<RecyclerView> rvQuotes;

        public DatabaseQuotesAsyncTask(QuoteDao quoteDao, RecyclerView rvQuotes) {
            this.quoteDao = quoteDao;
            this.rvQuotes = new WeakReference<>(rvQuotes);
        }

        @Override
        protected List<Quote> doInBackground(Void... voids) {
            return quoteDao.getAllQuotes();
        }

        @Override
        protected void onPostExecute(List<Quote> quotes) {
            QuotesAdapter adapter = new QuotesAdapter(quotes);
            rvQuotes.get().setAdapter(adapter);
        }
    }
}

This code is terrible. I mean, it is doing its job, but it is not testable, it is not scalable, it is not maintainable. We can’t test this code. MainActivity is 82 lines of code, just for displaying a list of quotes. Imagine if we add more calls here, more features in this screen (and usually there are more features), this code will easily become a mess.

How to fix this? We will start with a design pattern. We will refactor this code to follow the MVP pattern. Now, what is the MVP design pattern and how to implement it? MVP pattern is one of the most common design patterns. It is very close to MVC and MVVM. All of these design patterns (and others) share the idea that we should define and divide the responsibility of the classes. All of the mentioned design patterns above have 3 types of classes:

  • Model – data layer, used for managing business model classes
  • View – UI layer, used for displaying the data
  • Controller/Presenter/ViewModel – logic layer, intercepts the actions from the UI layer, updates the data and tells the UI layer to update itself

As you can see, Model and View classes are the same between all three patterns (they may have different responsibilities), the difference is the remaining class.

Let’s talk about MVP strictly, and try to convert our app to follow the MVP pattern. What classes belong to which type?

  • Model – Here belongs just the Quote class, so it stays the same
  • View – Here belong Activities and Fragments. In our case MainActivity
  • Presenter – We should create presenter for every Activity/Fragment

So, in the data layer (Model) we have just our Quote class and it stays the same. The View and the Presenter are left. Let’s create interfaces for the Views and Presenters. That way we will create the communication between them.

public interface BaseView<P> {
}

public interface BasePresenter<V> {
    void bindView(V view);
    void dropView();
}

Every Activity/Fragment should implement interfaces extending from BaseView, and every presenter should implement interfaces extending from BasePresenter. In MVP, the communication between the View and the Presenter is both ways (View <—> Presenter). This means that our Activity/Fragment should have an instance of the presenter and the presenter should have an instance of the view. Also, the Presenter should not contain any android component (easy check, you shouldn’t have any android, imports in the presenter). So, let’s create the View and the Presenter for MainActivity. I will organize the packages by feature because it is better when we follow some design patterns.

Now, we have MainActivity that implements MainView, and MainPresenterImpl that implements MainPresenter. We said that MainActivity should have an instance of MainPresenter and MainPresenterImpl should have an instance of MainView.

public interface MainPresenter extends BasePresenter<MainView> {
}

public class MainPresenterImpl implements MainPresenter {
    private MainView view;

    @Override
    public void bindView(MainView view) {
        this.view = view;
    }

    @Override
    public void dropView() {
        this.view = null;
    }
}

public interface MainView extends BaseView<MainPresenter> {
}

public class MainActivity extends AppCompatActivity implements MainView {
    //...
    private MainPresenter presenter;
   // ...
}

You will notice methods bindView() and dropView() in the presenter. That is because the view is responsible for its lifecycle, and it should inform the presenter about its presence/absence. In the lifecycle methods of the Activity/Fragment, we should call these methods. This should be done in one of these three pairs: In onCreate/onResume/onStart call bindView() and in onDestroy/onPause/onStart call dropView(). Use either one of the pairs, but you should not mix them. For example: Don’t call bindView() in onCreate and dropView() in onPause. Let’s call these methods in the MainActivity:

public class MainActivity extends AppCompatActivity implements MainView {
    //...
    private MainPresenter presenter;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        presenter = new MainPresenterImpl();
        presenter.bindView(this);

        //....
    }

    @Override
    protected void onDestroy() {
        presenter.dropView();
        super.onDestroy();
    }
}

Next, we should define methods in MainView and MainPresenter. In MainPresenter we want to get the quotes (it doesn’t matter for the view if the presenter gets them from the network or from the database) so we’ll create a method getAllQuotes(), and in the MainView we want to display the quotes, so we’ll create a method displayQuotes(List<Quote> quotes). After adding these methods in the interfaces, we will get compiler errors in the MainActivity and MainPresenterImpl. We need to implement these new methods. In the MainActivity we’ll just create a new adapter with the quotes and pass the adapter in the recyclerView. In the Presenter, it gets little trickier. We will move the network and database code from MainActivity to MainPresenterImpl, and whenever we create an adapter and set it to the recyclerView, we change that with calling displayQuotes() method of the MainView.

public class MainActivity extends AppCompatActivity implements MainView {
    //...
    @Override
    public void displayQuotes(List<Quote> quotes) {
        QuotesAdapter adapter = new QuotesAdapter(quotes);
        rvQuotes.setAdapter(adapter);
    }
}

// in presenter when we get the quotes
if (view != null) {
    view.displayQuotes(quotes);
}

Moreover, because QuoteDatabase requires context, and we can’t have a context in the Presenter, instead of creating QuoteDao inside the Presenter, we create it in MainActivity and pass it into the Presenter via the constructor. Finally, in the onCreate() method of the Activity, we call presenter.getAllQuotes(); You can check out the mvp_basic branch.

What have we done now? We refactored the MainActivity, to follow the MVP design pattern. Now, MainActvity has the responsibility only to display the quotes. It doesn’t need to be unit tested, because it doesn’t contain any logic. We moved the logic into the Presenter. But unfortunately, also the Presenter is hard to test now. We will try to make it better in the next article.

Testing asynchronous code in a concise and easy to read manner

Reading Time: 7 minutes

We live in a fast-paced world where a standard project delivery strategy is agile or it is a direction which people tend to follow. If you have been part of an agile software delivery practice then somewhere in your coding career you have met with some form of tests. Whether they might be unit or integration ( system ) or some form of E2E test.

You might be familiar with the testing pyramid and with the benefits and scopes of the different types of tests presented in the pyramid.

Let’s take a quick look at the pyramid:

Unit

As shown on the image above tests that we write are grouped into layers from which the pyramid is built. The foundation layer which is the biggest. It shows us their quantity. Meaning we need more of them on our application. They are also called Unit Tests because of the scope which they are testing. A small unit e.g. an if clause.

Integration/System

The tests belonging to the middle layer are called Integration tests and their purpose is to test integration between one or more elements inside an application and in quantitative representation we need fewer tests of this type than Unit tests.

UI/E2E

The last layer is the smallest one meaning that the quantity of those tests should be the smallest. Those types of tests are also called UI or E2E tests. Here a test has the biggest scope meaning that it is checking more interconnected parts of your application i.e whole register scenario from UI perspective.

As we go from the bottom to the top costs for maintenance are increasing, respectively their speed is decreasing. Confidence is also a crucial part. If a test higher in the pyramid passes we are more confident that our application works or some part of it at least.

Our focus is on the middle layer. So-called Integration tests lay there. As we mentioned above those are the tests that check the interconnection between one or more modules inside an application e.g tests which check that a user can be registered by pinging an endpoint. The scope of this test is to prepare data, send a request to the corresponding endpoint and also check whether the user has been successfully created in the underlying datastore. Testing integration between controller and repository layer, therefore, their name “An integration test”.
In my opinion, I think that tests are a must-have for every application.

Therefore we are writing integration tests for asynchronous code.

With multi-threaded data processing systems and increased popularity of reactive programming in Java, we are puzzled with writing proficient tests for asynchronous code.
Writing high-value tests is hard, but writing high-value tests for asynchronous code is harder.

Problem

Let’s take a look at this example where we have a small system that exposes several endpoints for updating a person. We have created several tests each is updating a person with different names. When a test is running it tries to update a person by sending a request via an endpoint. The system receives the request and returns ok status. In the meantime, it spans a different thread for the actual person update. On the side of the tests, we don’t know how much time does it gonna take for the update to happen so the naive approach is to wait for a specific time after which we are going to verify whether the actual update has happened.

We have several tests which ping a different endpoint. The endpoints are differing in the wait time that would be needed to process each request
updatePersonWith1SecondDelay
updatePersonWith2SecondDelay
updatePersonWith3SecondDelay
updatePersonWithDelayFrom1To5Seconds

In order for our tests to pass, I used the naive approach by adding a function waitForCompetition() which is nothing else than some sleep of the test thread. Thread.sleep() in Java.

Example

The first execution of tests with a timeout of 1 second. The total execution is 4 seconds but not all tests have passed.

The second execution of tests with a timeout of 3 seconds. The total execution is 12 seconds but not all tests have passed.

Third execution of tests with a timeout of 5 seconds. The total execution is 20 seconds where all tests have passed.

But in order for all the tests to pass, we would need a max of 5-second sleep wait which is executed after each test. This way we are guaranteeing that every test will pass. However, we add an unnecessary wait of 4 seconds for the first test and respectively add wait time for other tests. This results increased execution time, hence optimum wait time is not guaranteed.

Solution

As stated in the official documentation Awaitility is a small java library for synchronizing asynchronous operation. Which helps expressing expectations in a concise and easy to read manner. Which is a smart option for checking the outcome of some async operation.
It’s fairly easy to incorporate this library into your codebase.

You just need to add the library into pom.xml:

		<dependency>
			<groupId>org.awaitility</groupId>
			<artifactId>awaitility</artifactId>
			<version>3.0.0</version>
			<scope>test</scope>
		</dependency>

And add the import in your test:
import static org.awaitility.Awaitility.await;

Let’s take a look at an example before using this library:

@Test
    public void testDelay1Second() throws Exception {
        Person person = new Person();
        person.setName("Yara");
        person.setAddress("New York");
        person.setAge("23");
        personRepository.save(person);

        ObjectMapper mapper = new ObjectMapper();

        person.setName("Daenerys");

        this.mockMvc.perform(put("/api/endpoint1/" + person.getId())
                .contentType(APPLICATION_JSON)
                .content(mapper.writeValueAsBytes(person)))
                .andExpect(status().isOk())
                .andExpect(content().string(containsString("Request received")));

        waitForCompletion();
        assertThat(personRepository.findById(person.getId()).get().getName())
                .isEqualTo("Daenerys");
    }

An example with Awaitility:

@Test
    public void testDelay1Second() throws Exception {
        Person person = new Person();
        person.setName("Yara");
        person.setAddress("New York");
        person.setAge("23");
        personRepository.save(person);

        ObjectMapper mapper = new ObjectMapper();

        person.setName("Daenerys");

        this.mockMvc.perform(put("/api/endpoint1/" + person.getId())
                .contentType(APPLICATION_JSON)
                .content(mapper.writeValueAsBytes(person)))
                .andExpect(status().isOk())
                .andExpect(content().string(containsString("Request received")));

        await().atMost(Duration.FIVE_SECONDS).untilAsserted(() -> assertThat(personRepository.findById(person.getId()).get().getName())
                .isEqualTo("Daenerys"));
    }

Example of the executed test suite with the library:

As we can see the execution time is greatly reduced from 20 seconds for all tests to pass in just under 10 seconds.
As you can spot the function waitForCompletition() is removed and a new wait is introduced from the library as await().atMost(Duration.FIVE_SECONDS).untilAsserted()

You can also configure the library using static methods from the Awaitility class:
Awaitility.setDefaultPollInterval(10, TimeUnit.MILLISECONDS);
Awaitility.setDefaultPollDelay(Duration.ZERO);
Awaitility.setDefaultTimeout(Duration.ONE_MINUTE);

Conclusion

In this article, we have taken a look at how to improve tests when dealing with asynchronous code using an interesting library. I hope this post helps benefit you and adds to your knowledge. You can find a working example with all of the tests with and without the Awaitility library on this repository.
Also, you can find more about the library here.

Reactive Spring with WebFlux and SQL Databases

Reading Time: 6 minutes

Since SpringBoot 2 the Spring WebFlux was introduced so we can create reactive web applications. This was great and it was working fine with NoSql databases but when it came to relational databases this was an issue. The JDBC database operations are blocking by nature and this will stop you to create a totally non-blocking application. But in order to have an asynchronous and non-blocking application, we will need to cover every layer of the application. The hero that solved this was the R2DBC – Reactive Relational Database Connectivity that gives a possibility to make none-blocking calls to Relational Databases.

The combination of WebFlux and R2DBC is enough to cover every layer in our application that we are going to build. As a relational database, we are going to use H2. So on to the coding!

Go to the spring initializr page from where we are going to build our application and select the following configuration:

  • Group: com.north47 (or your package name)
  • Artifact: spring-r2dbc
  • Dependencies: Spring Reactive Web, Spring Data R2DBC [Experimental], H2 Database, Lombok

(You won’t be able to see the Lombok on this picture, but there it is! If for some reason the Lombok is causing you issues you might need to install a plugin. To do this in Intellij go to File -> Settings -> Plugins search for Lombok, install it and restart your IDE. If you can’t manage to do it just go the old way remove the annotations @Data, @AllArgsConstructor, @NoArgsConstructor in the Book.java class and just create your own setters, getters and constructors).

Now click on Generate, unzip the application and open it via your IDE.

Let’s first create a SQL script that will create our table. Go to src -> main -> resources and right-click on it and select New -> File. Name the file: schema.sql and enter there the following code:

CREATE TABLE BOOK (
ID INTEGER IDENTITY PRIMARY KEY ,
NAME VARCHAR(255) NOT NULL,
AUTHOR VARCHAR (255) NOT NULL
);

This will create a table with name ‘Book’ and the following columns: ID, NAME and AUTHOR.

We will create an additional script that will put us some data in our database. Repeat the following procedure from previous and this time give a name to the file: data.sql and add the following code:

INSERT INTO BOOK (ID,NAME,AUTHOR) VALUES (1,'Angels and Demons','Dan Brown');
INSERT INTO BOOK (ID,NAME, AUTHOR) VALUES (2,'The Matarese Circle', 'Robert Ludlum');
INSERT INTO BOOK (ID,NAME,AUTHOR) VALUES (3,'Name of the Rose', 'Umberto Eco');

This will put some data into our database.

In resources delete the application.properties file and let’s create a new file where we are going to add the following:

logging:
  level:
    org.springframework.data.r2dbc: DEBUG
spring:
  r2dbc:
    url: r2dbc:h2:mem:///test?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    name: sa
    password:


Now that we have defined the r2dbc URL and enabled DEBUG logging level for r2dbc let’s go to create our java classes.

Create a new package domain under the ‘com.north47.springr2dbc’ and create a new class Book. This will be our database model:

package com.north47.springr2dbc.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;

@Table("book")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {

    @Id
    private Long id;

    @Column(value = "name")
    private String name;

    @Column(value = "author")
    private String author;

}

Now to create our repository first create a new package named ‘repository’ under ‘com.north47.springrdbc’. In there create an interface named BookRepository. This interface will extend the R2dbRepository:

package com.north47.springr2dbc.repository;

import com.north47.springr2dbc.domain.Book;
import org.springframework.data.r2dbc.repository.R2dbcRepository;

public interface BookRepository extends R2dbcRepository<Book, Long> {
}

As you may notice we are not extending the JpaRepository as usual. The R2dbcRepository will provide us with methods that can work with objects like Flux, Mono etc…

After this, we will create endpoints from where we can access the previously inserted data or create new, modify it or delete it.

Create a new package ‘resource’ under the ‘com.north47.springr2dbc’ package and in there we will create our BookResource:

package com.north47.springr2dbc.resource;

import com.north47.springr2dbc.domain.Book;
import com.north47.springr2dbc.repository.BookRepository;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping(value = "/books")
public class BookResource {

    private final BookRepository bookRepository;

    public BookResource(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    @GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<Book> getAllBooks() {
        return bookRepository.findAll();
    }

    @GetMapping(value = "/{id}")
    public Mono<Book> findById(@PathVariable Long id) {
        return bookRepository.findById(id);
    }

    @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
    public Mono<Book> save(@RequestBody Book book) {
        return bookRepository.save(book);
    }

    @DeleteMapping(value = "/{id}")
    public Mono<Void> delete(@PathVariable Long id) {
        return bookRepository.deleteById(id);
    }
}

And there we have endpoints from where we can access our data and modify it.

On to the postman so we can test our application, but of course, first, let’s start it. When you run the application you can see in the console that your server is started:

Netty started on port(s): 8080

Also since we enabled DEBUG log level you should be able to see al the SQL queries that are executed from the scripts that we wrote previously.

In postman set a GET method and the url: localhost:8080/books. In the Headers add key: ‘Content-Type’, value:’application-json’.

Press that send button and there it is you will get the data:

data:{"id":1,"name":"Angels and Demons","author":"Dan Brown"}

data:{"id":2,"name":"The Matarese Circle","author":"Robert Ludlum"}

data:{"id":3,"name":"Name of the Rose","author":"Umberto Eco"}

You can test also the other endpoints, for example, getting a book by id just by changing the URL to localhost:8080/books/1. The result will be:

{
    "id": 1,
    "name": "Angels and Demons",
    "author": "Dan Brown"
}

Now you can test the other endpoints by creating a new Book by sending a POST request to the localhost:8080/books or delete a book by sending a DELETE to localhost:8080/books/{id}.

Here you can find the whole code:

Spring-R2DBC

Hope you enjoyed it!

Dependency injection and how I use it in Vaccination iOS app

Reading Time: 5 minutes

In programming, dependency injection is a technique where one object serves dependencies to another object. The concept is that instead of the client object to decide what kind of service it will use, another object tells to the client what service he has to use.

We can see the dependency injection as a software pattern. The fundament of this pattern is passing the service or object to the client, instead of allowing the client to find or to build the service on his own. What is the advantage of using this pattern? The main pros of this pattern are the readability of the code and code reusability.

Dependency injection – Injector example

Dependency injection is one form of the broader technique of inversion of control. The client delegates the responsibility of providing dependencies to external code (the injector) (Figure 1). The client is not allowed to call the injector code; it is injecting code that constructs the services and calls the client to inject them. This means the client code does not need to know about the injecting code, how to construct the services or even which actual services it is using; the client only needs to know about the intrinsic interfaces of the services because these define how the client may use the services. This separates the responsibilities of use and construction.

Types of DI

There are 3 types of dependency injection:

  1. Constructor injection: the dependencies are provided through a class constructor
  2. Setter injection: the client exposes a setter method that the injector uses to inject the dependency
  3. Interface injection: the dependency provides an injector method that will inject the dependency into any client passed to it. Clients must implement an interface that exposes a setter method that accepts the dependency

Vaccination app example

In the iOS world, the constructor injection is known as an initializer-based injection. This concept is realized with injecting the dependency object (or service) during initialization of the client class and this dependency is consistent/unchangeable during the life cycle of the client object.

In the previous few months, I’ve worked on the vaccination iOS application for N47 and I’ve decided to use the popular MVVM pattern inside. In the core of this pattern is the dependency injection. The components of the pattern are Model, View, and ViewModel, and each component is responsible for a different thing in the app. The point is to make the code more modular and easy to test.

The ViewModel (VM) component is a structure that contains only the data needed by the View component. The View component is presenting the data injected by the ViewModel. The ViewModel at other side is created by injecting dependency from the Model component. The main advantage of the MVVM is that we are creating views that have only one goal – presenting data. The view itself is not aware of the other task like fetching, persisting, etc.

We can see the initializer-based injection in action with the real example used in the Vaccination Demo App of N47. Let’s see first how the Details ViewModel looks like:

struct VaccineDetailsViewModel {
    let title: String
    let description: String
    let date: String?
}

The vaccine details view only needs title, description, and date for the vaccine. It doesn’t need more information. On the other hand, the vaccine model can contain more details about the vaccine, but this information is useless for the View. Inside the view controller (View component) we define view model property and set it via controller initializer. We can see this in the code snippet below:

 var vacineViewModel: VaccineDetailsViewModel?

class func createController(viewModel: VaccineDetailsViewModel?) -> VaccinesDetailViewController {
     
        let controller = VaccinesDetailViewController(nibName: "VaccinesDetailViewController", bundle: nil)
        controller.vacineViewModel = viewModel

        return controller
    }

This type of injection is preferable because it keeps us the safety of creating incomplete objects and with that, we will avoid coding mistakes.
So when I want to create a controller that will present the details for the vaccines and the scheduled vaccines I’m using injection via initializer in this way:

let details = VaccinesDetailViewController.createController(model: vaccination.createModel())

Other DI types in action…

In the Vaccination App, I’m also using Dependency Injection via setter creating the UITableView cells.

var vaccinationData: Vaccination? = nil {
        didSet {
            guard let vaccineId = vaccinationData?.vaccineId else { return }
            guard let vaccine = VaccineManager.sharedInstance.getVaccineById(vaccineId: vaccineId) else { return }
            let language = ModuleSharedPreferences.shared.language.rawValue
            let translation = vaccine.translations[language]
            
            vaccineTitleLabel.text = translation?.name
            vaccineApplyDateLabel.text = vaccinationData?.date
        }
    }

The code snippet above shows the vaccination data object that should be set with setter if we want the cell to be populated with data. Here is the code that will do the magic:

        let cell = tableView.dequeueReusableCell(withIdentifier: VaccinesTableViewCell.cellIdentifier, for: indexPath) as! VaccinesTableViewCell
        
        let vaccination = vaccinationList[indexPath.row]
        
        cell.vaccinationData = vaccination

Conclusion

Dependency injection is a powerful technique. Our code becomes more readable, reusable and easy for testing. We were able to see this technique in action in a real project and it was used within the popular design patterns MVVM. Using this technique we become sure that our components/services are completed, fully created before we start to use it.

Difference between Normal and Arrow Functions

Reading Time: 3 minutes

Arrow functions have been adopted since ECMAScript 2015. They are very powerful and simple. Many ES5-based projects adopted this feature to refactor the code. However, the arrow functions aren’t the same as the normal functions you’ve got to know. In this blog, I will explain what is the difference between normal and arrow functions.

This Keyword

A normal functions .this – binding is determined by who calls the function:

let a = 10;
let obj = { 
  hello,
  a: 20
};

function hello() {
  console.log(this.a);
}

hello(); // outputs 10
obj.hello(); //outputs 20

The method hello gives a different result by how it’s called. This is because a normal functions this is bound to the object that calls the function.

In contrast to a normal function, an arrow functions this is always bound to the outer function that surrounds the inner function:

let a = 10;
let hello = () =&gt; { 
  console.log(this.a);
};

let obj = {
  hello,
  a: 20
}

hello(); // outputs 10
obj.hello(); //outputs 10

In this example, hello is an arrow function. It’s a property of the obj. Even though obj calls hello, it still prints 10 because a function’ this always refers to the outer environments this. And the global this is a window so it points out to window.x.

Arguments

A normal function has a special property called argument:

function hello () {
  console.log(arguments.length)
};

hello(1, 2, 3); // outputs 3

hello(10); // outputs 1

An arrow function doesn’t have an arguments property:

let hello = () =&gt; {
  console.log(arguments.length)
};

hello(1, 2, 3); // outputs arguments is not defined

Binds

function.prototype.bind is a method you can use to change the this of the function:

let car = ‘Volvo’ 

function whatCar() {
  console.log(this.car)
};

whatCar(); // outputs ‘Volvo’
whatCar.bind({car: ‘Nissan’})() // outputs ‘Nissan’

whatCar prints the value depending on the assigned this.

But an arrow function doesn’t work with function.prototype.bind because it doesn’t have a local thisBinding. So it just looks at the outer environments this:

let car = ‘Volvo’ 

let whatCar = () =&gt; {
  console.log(this.car)
};

whatCar(); // outputs ‘Volvo’
whatCar.bind({car: ‘Nissan’})() // outputs ‘Volvo

Constructor

Normal function can be constructible and callable and arrow function is only callable and not constructible, they can never be invoked with the new keyword:

function hello () {};
let hi = () =&gt; {};
new hello(); // works
 hi(); // outputs hi is not a constructor

Arrow functions are more handy and stylish, but there are differences between arrow function and normal function. Maybe an arrow function won’t always be the best option to use. All I want to say is the best way to choose what function to use depends on each situation.

ReactiveX in Android with an example – RxJava

Reading Time: 5 minutes

What is Reactive Programming?

Reactive programming is programming with asynchronous data streams. It enables to create streams of anything – events, fails, variables, messages and etc. By using reactive programming in your application, you are able to create streams which you can then perform actions while the data emitted by those created streams.

Observer Pattern

The observer pattern is a software design pattern which defines a one-to-many relationship between objects. It means if the value/state of the observed object is changed/modified, the other objects which are observing are getting notified and updated.

ReactiveX

ReactiveX is a polyglot implementation of reactive programming which extends observer pattern and provides a bunch of data manipulation operators, threading abilities.

RxJava

RxJava is the JVM implementation of ReactiveX.

  • Observable – is a stream which emits the data
  • Observer – receives the emitted data from the observable
    • onSubscribe() – called when subscription is made
    • onNext() – called each time observable emits
    • onError() – called when an error occurs
    • onComplete() – called when the observable completes the emission of all items
  • Subscription – when the observer subscribes to observable to receive the emitted data. An observable can be subscribed by many observers
  • Scheduler – defines the thread where the observable emits and the observer receives it (for instance: background, UI thread)
    • subscribeOn(Schedulers.io())
    • observeOn(AndroidSchedulers.mainThread())
  • Operators – enable manipulation of the streamed data before the observer receives it
    • map()
    • flatMap()
    • concatMap() etc.

Example usage on Android

Tools, libraries, services used in the example:

  • Libraries:
    • ButterKnife – simplifying binding for android views
    • RxJava, RxAndroid – for reactive libraries
    • Retrofit2 – for network calls
  • Fake online rest API:
  • Java object generator from JSON file

What we want to achieve is to fetch users from 1. show in RecyclerView and load todo list to show the number of todos in the same RecyclerView without blocking the UI.

Here we define our endpoints. Retrofit2 supports return type of RxJava Observable for network calls.

    @GET("/users")
    Observable<List<User>> getUsers();

    @GET("/users/{id}/todos")
    Observable<List<Todo>> getTodosByUserID(@Path("id") int id);

    @GET("/todos")
    Observable<List<Todo>> getTodos();

Let’s fetch users:

  • .getUsers – returns observable of a list of users
  • .subscribeOn(Schedulers.io()) – make getUser() performs on background thread
  • .observeOn(AndroidSchedulers.mainThread()) – we switch to UI thread
  • flatMap – we set data to RecyclerView and return Observable user list which will be needed in fetching todo list
    private Observable<User> getUsersObservable() {
        return ServicesProvider.getDummyApi()
                .getUsers()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .flatMap((Function<List<User>, ObservableSource<User>>) users -> {
                    adapterRV.setData(users);
                    return Observable.fromIterable(users);
                });
    }

Now, fetch todo list of users using the 2nd endpoint.

Since we are not going to make another call, we don’t need Observable type in return of this method. So, here we use map() instead of flatMap() and we return User type.

    private Observable<User> getTodoListByUserId(User user) {
        return ServicesProvider.getDummyApi()
                .getTodosByUserID(user.getId())
                .subscribeOn(Schedulers.io())
                .map(todoList -> {
                    sleep();
                    user.setTodoList(todoList);
                    return user;
                });
    }

Now, fetch todo list of users using the 3rd endpoint.

The difference to the 2nd endpoint is that this returns a list of todos for all users. Here we can see the usage of filter() operator.

    private Observable<User> getAllTodo(User user) {
        return ServicesProvider.getDummyApi()
                .getTodos()
                .subscribeOn(Schedulers.io())
                .flatMapIterable((Function<List<Todo>, Iterable<Todo>>) todoList -> todoList)
                .filter(todo -> todo.getUserId().equals(user.getId()) &amp;&amp; todo.getCompleted())
                .toList().toObservable()
                .map(todoList -> {
                    sleep();
                    user.setTodoList(todoList);
                    return user;
                });
    }
  • .flatMapIterable() – is used to convert Observable<List<T>> to Observable<T> which is needed for filter each item in list
  • .filter() – we filter todos to get each user’s completed todo list
  • .toList().toObservable() – for converting back to Observable<List<T>>
  • .map() – we set filtered list to user object which will be used in next code snippet

Now, the last step, we call the methods:

        getUsersObservable()
                .subscribeOn(Schedulers.io())
                .concatMap((Function<User, ObservableSource<User>>) this::getTodoListByUserId) // operator can be concatMap()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<User>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        disposables.add(d);
                    }

                    @Override
                    public void onNext(User user) {
                        adapterRV.updateData(user);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.e(TAG, e.getMessage());
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "completed!");
                    }
                });
  • subscribeOn() – makes the next operator performed on background
  • concatMap() – here we call one of our methods getTodoListByUserId() or getAllTodo()
  • .observeOn(), .subscribe() – every time the user’s todo list is fetched from api in background thread, it emits the data and triggers onNext() so we update RecyclerView in UI thread
  • Left
    • getTodoListByUserId()
    • flatMap()
  • Right
    • concatMap()
    • getAllTodo() – filter usage

Difference between flatMap and concatMap is that the former is done in an arbitrary order but the latter preserves the order

Disposable

When an observer subscribes to an observable, a disposable object is provided in onSubscribe() method so it can later be used to terminate the background process to avoid it returning from callback to a dead activity.

private CompositeDisposable disposables = new CompositeDisposable();

observableobject.subscribe(new Observer() {
    @Override
    public void onSubscribe(Disposable d) {
        disposables.add(d);
    }

@Override
protected void onDestroy() {
    super.onDestroy();
    disposables.dispose();
}

Summary

In this post, I tried to give brief information about reactive programming, observer pattern, ReactiveX library and a simple example on android.

Why should you use RxJava in your projects?

  • less boilerplate code
  • easy thread management
  • thread-safety
  • easy error handling

Gitlab Repository

Example sourcecode: https://gitlab.com/47northlabs/public/android-rxjava

Links

Experiences of FrontendConnect 2019 conference Warsaw, Poland

Reading Time: 4 minutes

INTRODUCTION

Everybody has an open lifetime book full of blank pages, waiting to be filled. We write the story as we go, so back in November 2019, I have started the chapter ‘Frontend conferences’ by attending the FrontendConnect2019 in Warsaw, Poland, thanks to my company N47.

My motivation to choose this conference was the fact that I will gain new knowledge, and exchange practical ways of using frontend frameworks. Despite this, given the fact that there were great speakers from the IT world, I had no doubt choosing this tech event. Duration of the event was three days, one workshop day and two speaking conference days.

WHICH WORKSHOP DID I ATTEND TO?

As I was experienced with Vue.js, I wanted to upgrade the knowledge with Nuxt as their workshop description was “It may take it to the next level, thanks to its convention over configuration approach.” I got a certificate of attendance and completion of “My first Nuxt.js application” by the Vue.js Core Team member Darek ‘Gusto’ Wędrychowski. Coding under the eye of ‘Gusto’ and having a wonderful panorama view of Warsaw in my horizon, was definitely a day well spent.

WHICH PRESENTATION DID I ATTEND TO?

Rich agenda with scheduled talks, thoughts about which ones to choose, moreover similar questions were going through my mind. I attended the ones that caught my eye and were mostly within my interests.

At the beginning of each day, there was a high valued speaker opening the day with their talks. The first day I had to meet and listen to the very appreciated, Douglas Crockford with his JSON Saga.

The second day, there was Minko Gechev, a Google engineer working on the Angular framework with the talk ‘The Future of Front-End Frameworks’.

Some other topics that I attended to were about the state management in a world of hooks, some optimizations of the modern JavaScript applications and loading them instantly, as well as Angular and Vue.js 3.0 topics.

WHAT CAUGHT MY MIND?

Two of my favourite talks were ‘The JSON Saga’ – Douglas Crockford and ‘Vue 3.0 for Library Authors’ – Damian Dulisz.

The JSON Saga

Douglas was retelling the story about how he discovered JSON (JavaScript Object Notation). He explained how he did not invent, but found it in the early 2000s, named it and described its usefulness. JSON is a format for storing data and establishing communication between the servers. He explained how some companies complained and did not want to accept JSON because they were used to XML, and could not consider anything else, at that moment. He mentioned that some of the people denied its usage because of it not being a standard. So, what he did next was buying JSON.org, a website which after a few years spread among the users. After a while, JSON got the support of all languages. He announced that there will be no more changes to JSON because for him there is no feature more important than the stability of JSON.

Vue 3.0 for Library Authors

Getting more in details about this topic and Vue 3.0-alpha version will be covered in my next blog.

THE CULTURE AND ENVIRONMENT IN THE CONFERENCE

Frontend Connect was happening in the theatre of the Palace of Culture and Science in Warsaw, Poland where the history and modern world meet at the same time. It is one of the symbolic icons of Warsaw and the place of the city`s rebirth. There were people from all over the world, and the atmosphere was really friendly. Everybody was discussing the topics and shared their work ethics.

CONCLUSION

Visiting conferences is a really good way to meet new friendly people that you have a lot in common with, as well as having an opportunity to reach out to the speaker if you enjoyed the talk, and discuss what you found interesting. We should always strive for more experiences like this and face new challenges within modern technologies. With that being said, we need to nurture our idea to reach our full potential, in order to make a bigger impact in the IT world.