<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>tutorial Archives | Clever Cloud</title>
	<atom:link href="https://stagingv6.cleverapps.io/blog/tag/tutorial/feed/" rel="self" type="application/rss+xml" />
	<link></link>
	<description>From Code to Product</description>
	<lastBuildDate>Tue, 04 May 2021 09:15:00 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2023/03/cropped-cropped-favicon-32x32.png</url>
	<title>tutorial Archives | Clever Cloud</title>
	<link></link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How to deploy Apache Superset on Clever Cloud</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2021/05/04/how-to-deploy-apache-superset-on-clever-cloud/</link>
		
		<dc:creator><![CDATA[Aurélien Hebert]]></dc:creator>
		<pubDate>Tue, 04 May 2021 09:15:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2021/05/04/how-to-deploy-apache-superset-on-clever-cloud/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" fetchpriority="high" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1-1368x528.jpg 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p>At Clever Cloud we manage most of our own data and when we want to gather a particular information, we open our SQL interpreter and query all the things manually. This somehow worked because most of us are technical but it's not necessary the case anymore. So we want a nice dashboarding solution to make data available in a nicer way. This is how we came to try Superset.

<span id="more-2834"></span>

What is Superset? In their own words:
<blockquote>Superset is fast, lightweight, intuitive, and loaded with options that make it easy for users of all skill sets to explore and visualize their data.</blockquote>
You can configure different sort of visualizations from simple line charts to highly detailed geo-spatial charts and organize them in dashboard. Take a look at <a href="https://superset.apache.org/">their documentation</a> to grasp the full extent of what you can do.
<h2 id="how-to-deploy-superset">How to deploy Superset</h2>
Superset is written in Python and requires a PostgreSQL database. In Clever Cloud terms it means you will need to create a brand <a href="https://stagingv6.cleverapps.io/doc/deploy/application/python/python_apps/">new Python runtime</a> with a <a href="https://stagingv6.cleverapps.io/doc/deploy/addon/postgresql/">PostgreSQL addon</a>.
<pre><code class="language-bash"># Clone last superset release
git clone --depth 1 -b 0.38.1  https://github.com/apache/superset.git

# Move in superset repository
cd superset

# Create the python application
clever create --type python Superset

# Create the PostgreSQL instance                                
clever addon create postgresql-addon --plan m SupersetPG
    
# link the addon 
clever service link-addon SupersetPG
</code></pre>
Once the application is created, edit it's information. As you need to build Superset backend and frontend, you need to enable a <a href="https://stagingv6.cleverapps.io/doc/administrate/apps-management/#edit-application-configuration">dedicated build instance</a>, select the <code>L</code> one. Don't foget to save the update.
<h3 id="superset-environment">Superset environment</h3>
Set the following environment, <code>YOUR_APP_ID</code> corresponds to your own application id, <code>A_SECRET_KEY</code> is a random secret key you choose, and <code>AN_ADMIN_PASSWORD</code> will be the admin password for the superset application:
<pre><code class="language-bash"># Use gunicorn as python mode 
clever env set CC_PYTHON_BACKEND gunicorn

# Start the app using create_app() 
clever env set CC_PYTHON_MODULE superset.app:create_app()

# Python version to use
clever env set CC_PYTHON_VERSION 3.7

# Load all superset requirements
clever env set CC_PIP_REQUIREMENTS_FILE requirements/base.txt

# Application port
clever env set PORT 8080

# PYTHONPATH
clever env set PYTHONPATH /home/bas/YOUR_APP_ID/config/

# App secret key
clever env set SECRET_KEY A_SECRET_KEY

# Post build commands
clever env set CC_POST_BUILD_HOOK ./init.sh

# Superset admin password
clever env set ADMIN_PASSWORD AN_ADMIN_PASSWORD
</code></pre>
<h3 id="configure-superset">Configure superset</h3>
Superset need a local config python file. Wrote locally a <code>clever_config.py</code>:
<pre><code class="language-python">import os
# Superset specific config
ROW_LIMIT = 5000

SUPERSET_WEBSERVER_PORT = os.getenv("PORT")
SUPERSET_WEBSERVER_ADDRESS = "0.0.0.0"

# Flask App Builder configuration
# Your App secret key
SECRET_KEY = os.getenv("SECRET_KEY")

# The SQLAlchemy connection string to your database backend
# This connection defines the path to the database that stores your
# superset metadata (slices, connections, tables, dashboards, ...).
# Note that the connection information to connect to the datasources
# you want to explore are managed directly in the web UI
SQLALCHEMY_DATABASE_URI = os.getenv("POSTGRESQL_ADDON_URI")

# Flask-WTF flag for CSRF
WTF_CSRF_ENABLED = True
# Add endpoints that need to be exempt from CSRF protection
WTF_CSRF_EXEMPT_LIST = []
# A CSRF token that expires in 1 year
WTF_CSRF_TIME_LIMIT = 60 * 60 * 24 * 365

# Set this API key to enable Mapbox visualizations
MAPBOX_API_KEY = ''
</code></pre>
<h3 id="superset-build-scipt">Superset build scipt</h3>
The next step is to write an <code>init.sh</code>file that will include all build tasks for superset:
<pre><code class="language-bash">#!/bin/bash

# Load configuration file in PYTHONPATH
mkdir $APP_HOME/config
cp clever_config.py $APP_HOME/config/superset_config.py

# Create an admin user (you will be prompted to set username, first and last name before setting a password)
superset fab create-admin \
    --username admin \
    --firstname admin \
    --lastname admin \
    --email admin@admin.com \
    --password ${ADMIN_PASSWORD}

# Upgrade the database
superset db upgrade

# Loading examples data set (optional)
superset load_examples

# Create default roles and permissions
superset init

# Build frontend
cd superset-frontend 
npm install -f --no-optional
npm run build
</code></pre>
Clever supports <a href="https://stagingv6.cleverapps.io/doc/develop/build-hooks/#post-build-cc_post_build_hook">post build hooks</a>, this <code>init.sh</code> file will be played at the end of the build phase.

It's used to set the config file we wrote before into <code>PYTHONPATH</code> used by the application. Then it will start some superset commands required for the first start of the application (create the admin user if it doesn't exists, upgrade the database, and file it with examples and finally init the superset appication). Those superset commands could be remove of the init file after the first success build. Finally, this script is used to also build the frontend of the superset application.
<h3 id="superset-requirements">Superset requirements</h3>
When you added the <code>CC_PIP_REQUIREMENTS_FILE</code>, it told clever cloud to load custom requirement for superset which are locate in the <code>requirements/base.txt</code> file. As you are using the PostgreSQL add-on, you need to add its requirement in this base file:
<pre><code class="language-bash">echo "psycopg2&gt;=2.7 --no-binary psycopg2" &gt;&gt; requirements/base.txt
</code></pre>
The Clever Cloud python application still needs a local <code>requirements.txt</code> to start the install. Generate it with:
<pre><code class="language-bash">pip3 freeze &gt; requirements.txt 
</code></pre>
As we use gunicorn and the PostgreSQL add-on, they are required in the <code>requirements.txt</code> file, add them:
<pre><code class="language-bash">echo "psycopg2&gt;=2.7 --no-binary psycopg2" &gt;&gt; requirements.txt

# gunicorn valid versions are located in setup.py file
echo "gunicorn&gt;=20.0.2, &lt;20.1" &gt;&gt; requirements.txt
</code></pre>
<h3 id="deploy">Deploy</h3>
Deploy the superset application into Clever cloud:
<pre><code class="language-bash">chmod u+x init.sh

# Add your files
git add .

# Create the first commit
git commit -m "clever init"

# Deploy the application
clever deploy

# Run the application
clever open
</code></pre>
Once this is done you should be able to access the superset application, enjoy!

After the first successful <code>superset</code> deployement you can remove on the <code>init.sh</code> file all commands starting with superset (they are required for the first start).]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/superset-1-1368x528.jpg 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p>At Clever Cloud we manage most of our own data and when we want to gather a particular information, we open our SQL interpreter and query all the things manually. This somehow worked because most of us are technical but it's not necessary the case anymore. So we want a nice dashboarding solution to make data available in a nicer way. This is how we came to try Superset.

<span id="more-2834"></span>

What is Superset? In their own words:
<blockquote>Superset is fast, lightweight, intuitive, and loaded with options that make it easy for users of all skill sets to explore and visualize their data.</blockquote>
You can configure different sort of visualizations from simple line charts to highly detailed geo-spatial charts and organize them in dashboard. Take a look at <a href="https://superset.apache.org/">their documentation</a> to grasp the full extent of what you can do.
<h2 id="how-to-deploy-superset">How to deploy Superset</h2>
Superset is written in Python and requires a PostgreSQL database. In Clever Cloud terms it means you will need to create a brand <a href="https://stagingv6.cleverapps.io/doc/deploy/application/python/python_apps/">new Python runtime</a> with a <a href="https://stagingv6.cleverapps.io/doc/deploy/addon/postgresql/">PostgreSQL addon</a>.
<pre><code class="language-bash"># Clone last superset release
git clone --depth 1 -b 0.38.1  https://github.com/apache/superset.git

# Move in superset repository
cd superset

# Create the python application
clever create --type python Superset

# Create the PostgreSQL instance                                
clever addon create postgresql-addon --plan m SupersetPG
    
# link the addon 
clever service link-addon SupersetPG
</code></pre>
Once the application is created, edit it's information. As you need to build Superset backend and frontend, you need to enable a <a href="https://stagingv6.cleverapps.io/doc/administrate/apps-management/#edit-application-configuration">dedicated build instance</a>, select the <code>L</code> one. Don't foget to save the update.
<h3 id="superset-environment">Superset environment</h3>
Set the following environment, <code>YOUR_APP_ID</code> corresponds to your own application id, <code>A_SECRET_KEY</code> is a random secret key you choose, and <code>AN_ADMIN_PASSWORD</code> will be the admin password for the superset application:
<pre><code class="language-bash"># Use gunicorn as python mode 
clever env set CC_PYTHON_BACKEND gunicorn

# Start the app using create_app() 
clever env set CC_PYTHON_MODULE superset.app:create_app()

# Python version to use
clever env set CC_PYTHON_VERSION 3.7

# Load all superset requirements
clever env set CC_PIP_REQUIREMENTS_FILE requirements/base.txt

# Application port
clever env set PORT 8080

# PYTHONPATH
clever env set PYTHONPATH /home/bas/YOUR_APP_ID/config/

# App secret key
clever env set SECRET_KEY A_SECRET_KEY

# Post build commands
clever env set CC_POST_BUILD_HOOK ./init.sh

# Superset admin password
clever env set ADMIN_PASSWORD AN_ADMIN_PASSWORD
</code></pre>
<h3 id="configure-superset">Configure superset</h3>
Superset need a local config python file. Wrote locally a <code>clever_config.py</code>:
<pre><code class="language-python">import os
# Superset specific config
ROW_LIMIT = 5000

SUPERSET_WEBSERVER_PORT = os.getenv("PORT")
SUPERSET_WEBSERVER_ADDRESS = "0.0.0.0"

# Flask App Builder configuration
# Your App secret key
SECRET_KEY = os.getenv("SECRET_KEY")

# The SQLAlchemy connection string to your database backend
# This connection defines the path to the database that stores your
# superset metadata (slices, connections, tables, dashboards, ...).
# Note that the connection information to connect to the datasources
# you want to explore are managed directly in the web UI
SQLALCHEMY_DATABASE_URI = os.getenv("POSTGRESQL_ADDON_URI")

# Flask-WTF flag for CSRF
WTF_CSRF_ENABLED = True
# Add endpoints that need to be exempt from CSRF protection
WTF_CSRF_EXEMPT_LIST = []
# A CSRF token that expires in 1 year
WTF_CSRF_TIME_LIMIT = 60 * 60 * 24 * 365

# Set this API key to enable Mapbox visualizations
MAPBOX_API_KEY = ''
</code></pre>
<h3 id="superset-build-scipt">Superset build scipt</h3>
The next step is to write an <code>init.sh</code>file that will include all build tasks for superset:
<pre><code class="language-bash">#!/bin/bash

# Load configuration file in PYTHONPATH
mkdir $APP_HOME/config
cp clever_config.py $APP_HOME/config/superset_config.py

# Create an admin user (you will be prompted to set username, first and last name before setting a password)
superset fab create-admin \
    --username admin \
    --firstname admin \
    --lastname admin \
    --email admin@admin.com \
    --password ${ADMIN_PASSWORD}

# Upgrade the database
superset db upgrade

# Loading examples data set (optional)
superset load_examples

# Create default roles and permissions
superset init

# Build frontend
cd superset-frontend 
npm install -f --no-optional
npm run build
</code></pre>
Clever supports <a href="https://stagingv6.cleverapps.io/doc/develop/build-hooks/#post-build-cc_post_build_hook">post build hooks</a>, this <code>init.sh</code> file will be played at the end of the build phase.

It's used to set the config file we wrote before into <code>PYTHONPATH</code> used by the application. Then it will start some superset commands required for the first start of the application (create the admin user if it doesn't exists, upgrade the database, and file it with examples and finally init the superset appication). Those superset commands could be remove of the init file after the first success build. Finally, this script is used to also build the frontend of the superset application.
<h3 id="superset-requirements">Superset requirements</h3>
When you added the <code>CC_PIP_REQUIREMENTS_FILE</code>, it told clever cloud to load custom requirement for superset which are locate in the <code>requirements/base.txt</code> file. As you are using the PostgreSQL add-on, you need to add its requirement in this base file:
<pre><code class="language-bash">echo "psycopg2&gt;=2.7 --no-binary psycopg2" &gt;&gt; requirements/base.txt
</code></pre>
The Clever Cloud python application still needs a local <code>requirements.txt</code> to start the install. Generate it with:
<pre><code class="language-bash">pip3 freeze &gt; requirements.txt 
</code></pre>
As we use gunicorn and the PostgreSQL add-on, they are required in the <code>requirements.txt</code> file, add them:
<pre><code class="language-bash">echo "psycopg2&gt;=2.7 --no-binary psycopg2" &gt;&gt; requirements.txt

# gunicorn valid versions are located in setup.py file
echo "gunicorn&gt;=20.0.2, &lt;20.1" &gt;&gt; requirements.txt
</code></pre>
<h3 id="deploy">Deploy</h3>
Deploy the superset application into Clever cloud:
<pre><code class="language-bash">chmod u+x init.sh

# Add your files
git add .

# Create the first commit
git commit -m "clever init"

# Deploy the application
clever deploy

# Run the application
clever open
</code></pre>
Once this is done you should be able to access the superset application, enjoy!

After the first successful <code>superset</code> deployement you can remove on the <code>init.sh</code> file all commands starting with superset (they are required for the first start).]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Rails 4 apps backed by Sidekiq + Clever Cloud.</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2015/05/05/deploy-a-rails-app-using-sidekiq-on-clever-cloud/</link>
		
		<dc:creator><![CDATA[Julien Durillon]]></dc:creator>
		<pubDate>Tue, 05 May 2015 15:32:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2015/05/05/deploy-a-rails-app-using-sidekiq-on-clever-cloud/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1-1368x528.jpg 1368w" sizes="(max-width: 1400px) 100vw, 1400px" /></p><p>At Clever Cloud, we want developers to be happy. To achieve that we try to adapt as quickly as we can to users needs. The other day, someone asked for <a href="http://sidekiq.org/">Sidekiq</a> support for their Rails applications.</p>
<span id="more-2798"></span>

<h2 id="whats-sidekiq">What&#39;s Sidekiq</h2>
<p>Sidekiq is a solution to run long background tasks in ruby. It works by running a background server and treating jobs stored in a Redis. It&#39;s helpful to delay tasks, take a long API call to the background while still be able to answer to a request in a timely manner.</p>
<h2 id="how-do-i-use-sidekiq-on-clever-cloud">How do I use Sidekiq on Clever Cloud?</h2>
<p>First, you need a Redis instance. Start by provisioning a redis addon on Clever Cloud. Remember to link the redis add-on to your application in the Console.</p>
<p>The redis addon provides a <code>REDIS_URL</code> environment variable which will be used by sidekiq to connect to the redis addon.</p>
<ul>
<li>The next and only step is to add/modify the <code>clevercloud/ruby.json</code> file to add the
&quot;sidekiq&quot; flag:</li>
</ul>
<pre><code class="language-json">{
   &quot;deploy&quot;: {
      &quot;sidekiq&quot;: true
   }
}
</code></pre>
<p>Then commit and push your application, and you should be all set!</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/rails4-sidekiq-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>At Clever Cloud, we want developers to be happy. To achieve that we try to adapt as quickly as we can to users needs. The other day, someone asked for <a href="http://sidekiq.org/">Sidekiq</a> support for their Rails applications.</p>
<span id="more-2798"></span>

<h2 id="whats-sidekiq">What&#39;s Sidekiq</h2>
<p>Sidekiq is a solution to run long background tasks in ruby. It works by running a background server and treating jobs stored in a Redis. It&#39;s helpful to delay tasks, take a long API call to the background while still be able to answer to a request in a timely manner.</p>
<h2 id="how-do-i-use-sidekiq-on-clever-cloud">How do I use Sidekiq on Clever Cloud?</h2>
<p>First, you need a Redis instance. Start by provisioning a redis addon on Clever Cloud. Remember to link the redis add-on to your application in the Console.</p>
<p>The redis addon provides a <code>REDIS_URL</code> environment variable which will be used by sidekiq to connect to the redis addon.</p>
<ul>
<li>The next and only step is to add/modify the <code>clevercloud/ruby.json</code> file to add the
&quot;sidekiq&quot; flag:</li>
</ul>
<pre><code class="language-json">{
   &quot;deploy&quot;: {
      &quot;sidekiq&quot;: true
   }
}
</code></pre>
<p>Then commit and push your application, and you should be all set!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Building an extensible HTTP client for GitHub in Java</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2015/03/24/simple-http-client-in-java/</link>
		
		<dc:creator><![CDATA[Marc-Antoine Perennou]]></dc:creator>
		<pubDate>Tue, 24 Mar 2015 16:32:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2015/03/24/simple-http-client-in-java/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>At Clever Cloud, we use a lot of Java. A large part of our API is written using JEE (aka Java Enterprise Edition). Here is how we implemented the http client we use for <a href="https://stagingv6.cleverapps.io/blog/features/2014/12/03/login-via-github/">our Github integration</a>.</p>
<span id="more-2796"></span>

<p>The standard HTTP implementation in JEE is <a href="https://jersey.java.net/">Jersey</a>, so that&#39;s what we&#39;ll use here.</p>
<h3 id="a-bit-of-background-first">A bit of background first</h3>
<p>Our API is designed in a &quot;micro-services&quot; way. There&#39;s a central part and various external components.</p>
<p>Here, we&#39;ll be dealing with the central part, which itself is internally designed in a sort-of &quot;micro-services&quot; way. JEE offers a powerful dependency injection mechanism called CDI, which we use to build a lot of small tools we can then use just as we need.</p>
<h3 id="serialization">Serialization</h3>
<p>When you&#39;re building APIs and clients, one of the problematics is about serialization. We made a tool to do just that which you&#39;ll see in the code as <code>MapperHelper</code>, namely <code>mh</code>. It&#39;s basically a wrapper around <a href="https://github.com/FasterXML/jackson">jackson</a>&#39;s <code>ObjectMapper</code>.</p>
<h3 id="lets-get-to-work">Let&#39;s get to work</h3>
<p>We&#39;ll be working on an internal tool called <code>GithubAPIHelper</code>. We&#39;ll not get through the whole of it, but you&#39;ll quickly get the concept.</p>
<p>First, some standard JEE boilerplate injecting required tools using CDI.</p>
<pre><code class="language-java">@Stateless
public class GithubAPIHelper {

   @Inject
   private MapperHelper mh;
   @Inject
   private LogsHelper lh;

   private final static String GITHUB_URL = &quot;https://api.github.com&quot;;
}
</code></pre>
<p>Now, we want to build an HTTP client using <code>jersey-client</code>, this is pretty straightforward. Btw, we create a method to make the client directly point at Github.</p>
<pre><code class="language-java">private Client getClient() {
   if (client == null) {
      client = ClientBuilder.newClient(new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS, true));
   }
   return client;
}

private WebTarget getTarget() {
   return getClient().target(GITHUB_URL);
}
</code></pre>
<p>What about authentication? Let&#39;s create a new method to get an authenticated request to Github:</p>
<pre><code class="language-java">private Invocation.Builder getBuilder(WebTarget target, String token) {
   return target.request().header(&quot;Authorization&quot;, &quot;token &quot; + token);
}
</code></pre>
<p>Ok, now that we have those basic pieces in place, we can start requesting for real.</p>
<p>Let&#39;s get the basic user profile, for starters</p>
<p>First, we create a basic data structure that we&#39;ll use to deserialize the payload from Github. I&#39;ll skip most of the available fields here as they&#39;re not needed.</p>
<pre><code class="language-java">public class GithubOwner implements Serializable {

   public int id;
   public String name;
   public String login;
   public String email;
   public String avatar_url;
}
</code></pre>
<p>Now, you should all be yelling at me about those public fields. Let me remember you that this data structure is only used for deserializing purpose, it won&#39;t ever be used for anything else, so what&#39;s the point in complicating things?</p>
<p>Now let&#39;s get back to business, we have a way to construct authenticated requests, and a model in which to store the data. So let&#39;s do it!</p>
<p>First, let&#39;s get to the right endpoint: <code>/user</code></p>
<pre><code class="language-java">   getTarget().path(&quot;/user&quot;);
</code></pre>
<p>Now, let&#39;s actually issue the request, and get a response</p>
<pre><code class="language-java">   Response r = getBuilder(getTarget().path(&quot;/user&quot;), token).get();
</code></pre>
<p>Let&#39;s deserialize the data from github</p>
<pre><code class="language-java">   GithubOwner owner = mh.readValue(r.readEntity(String.class), GithubOwner.class);
</code></pre>
<p>And here we are, with some integrity checks added:</p>
<pre><code class="language-java">   public GithubOwner getSelf(String token) {
      Response r = getBuilder(getTarget().path(&quot;/user&quot;), token).get();
      if (r.getStatus() &lt; 300) {
         try {
            GithubOwner owner = mh.readValue(r.readEntity(String.class), GithubOwner.class);
            return owner;
         } catch (IOException e) {
            lh.log(GithubAPIHelper.class.getName(), Level.SEVERE, null, e);
         }
      }
      return null;
   }
</code></pre>
<h3 id="dealing-with-pagination">Dealing with pagination</h3>
<p>Getting the user&#39;s profile was quite easy and straightforward, but everything isn&#39;t that smooth.</p>
<p>Let&#39;s say we now want all the repositories, instinctively, here is what we&#39;d do:</p>
<pre><code class="language-java">public class GithubRepository implements Serializable {

   public long id;
   public String name;
   public String description;
   public GithubOwner owner;
   @JsonProperty(value = &quot;private&quot;)
   public boolean isPrivate;
   public String ssh_url;
   public String git_url;
}
</code></pre>
<pre><code class="language-java">   private TypeSafeList&lt;GithubRepository&gt; getSelfRepositories(String token) {
      TypeSafeList&lt;GithubRepository&gt; repos = new TypeSafeArrayList&lt;&gt;();
      Response r = getBuilder(getTarget().path(&quot;/user/repos&quot;), token).get();
      if (r.getStatus() &lt; 300) {
         try {
            List&lt;GithubRepository&gt; ms = mh.readValue(r.readEntity(String.class), new TypeReference&lt;List&lt;GithubRepository&gt;&gt;() {
            });
            repos.addAll(new TypeSafeArrayList&lt;&gt;(ms));
         } catch (IOException e) {
            lh.log(GithubAPIHelper.class.getName(), Level.SEVERE, null, e);
         }
      }
      return repos;
   }
</code></pre>
<p>That will actually work, but you won&#39;t get all of them, only the first 20 or so. If you want all of them, you&#39;ll have to follow the pagination.</p>
<p>First, we want to get the link marked as <code>rel=next</code> in the <code>Link</code> http header.</p>
<pre><code class="language-java">   private String getNextLink(Response r) {
      String link = r.getHeaderString(&quot;Link&quot;);   /* &lt;http://foobar&gt;; rel=&quot;next&quot;, &lt;http://blah/&gt;; rel=last */
      if (link != null) {
         String[] links = link.split(&quot;,&quot;);
         for (String l : links) {               /* &lt;http://foobar&gt;; rel=&quot;next&quot; */
            if (l.contains(&quot;rel=\&quot;next\&quot;&quot;)) {
               String[] tmp1 = l.split(&quot;&lt;&quot;, 2);
               if (tmp1.length == 2) {
                  return tmp1[1].split(&quot;&gt;&quot;, 2)[0];  /* http://foobar */
               }
            }
         }
      }
      return null;
   }
</code></pre>
<p>Next, we want to request this url and get the next data to our initial request</p>
<pre><code class="language-java">   private Response getNextData(Response r, String token) {
      String link = getNextLink(r);
      if (link == null)
         return null;
      return getBuilder(getClient().target(link), token).get();
   }
</code></pre>
<p>Now let&#39;s put all the pieces together, addind a loop to retrieve all the data</p>
<pre><code class="language-java">   private TypeSafeList&lt;GithubRepository&gt; getSelfRepositories(String token) {
      TypeSafeList&lt;GithubRepository&gt; repos = new TypeSafeArrayList&lt;&gt;();
      Response r = getBuilder(getTarget().path(&quot;/user/repos&quot;), token).get();
      while (r != null) {
         if (r.getStatus() &lt; 300) {
            try {
               List&lt;GithubRepository&gt; ms = mh.readValue(r.readEntity(String.class), newhTypeReference&lt;List&lt;GithubRepository&gt;&gt;() {
               });
               repos.addAll(new TypeSafeArrayList&lt;&gt;(ms));
            } catch (IOException e) {
               lh.log(GithubAPIHelper.class.getName(), Level.SEVERE, null, e);
            }
         }
         r = getNextData(r, token);
      }
      return repos;
   }
</code></pre>
<p>And voila, you now have a working Github HTTP client. Once you got these, the other endpoints are really easy.</p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1.jpg" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1.jpg 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1-300x116.jpg 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1-1024x395.jpg 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1-768x296.jpg 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/http-client-java-1-1368x528.jpg 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>At Clever Cloud, we use a lot of Java. A large part of our API is written using JEE (aka Java Enterprise Edition). Here is how we implemented the http client we use for <a href="https://stagingv6.cleverapps.io/blog/features/2014/12/03/login-via-github/">our Github integration</a>.</p>
<span id="more-2796"></span>

<p>The standard HTTP implementation in JEE is <a href="https://jersey.java.net/">Jersey</a>, so that&#39;s what we&#39;ll use here.</p>
<h3 id="a-bit-of-background-first">A bit of background first</h3>
<p>Our API is designed in a &quot;micro-services&quot; way. There&#39;s a central part and various external components.</p>
<p>Here, we&#39;ll be dealing with the central part, which itself is internally designed in a sort-of &quot;micro-services&quot; way. JEE offers a powerful dependency injection mechanism called CDI, which we use to build a lot of small tools we can then use just as we need.</p>
<h3 id="serialization">Serialization</h3>
<p>When you&#39;re building APIs and clients, one of the problematics is about serialization. We made a tool to do just that which you&#39;ll see in the code as <code>MapperHelper</code>, namely <code>mh</code>. It&#39;s basically a wrapper around <a href="https://github.com/FasterXML/jackson">jackson</a>&#39;s <code>ObjectMapper</code>.</p>
<h3 id="lets-get-to-work">Let&#39;s get to work</h3>
<p>We&#39;ll be working on an internal tool called <code>GithubAPIHelper</code>. We&#39;ll not get through the whole of it, but you&#39;ll quickly get the concept.</p>
<p>First, some standard JEE boilerplate injecting required tools using CDI.</p>
<pre><code class="language-java">@Stateless
public class GithubAPIHelper {

   @Inject
   private MapperHelper mh;
   @Inject
   private LogsHelper lh;

   private final static String GITHUB_URL = &quot;https://api.github.com&quot;;
}
</code></pre>
<p>Now, we want to build an HTTP client using <code>jersey-client</code>, this is pretty straightforward. Btw, we create a method to make the client directly point at Github.</p>
<pre><code class="language-java">private Client getClient() {
   if (client == null) {
      client = ClientBuilder.newClient(new ClientConfig().property(ClientProperties.FOLLOW_REDIRECTS, true));
   }
   return client;
}

private WebTarget getTarget() {
   return getClient().target(GITHUB_URL);
}
</code></pre>
<p>What about authentication? Let&#39;s create a new method to get an authenticated request to Github:</p>
<pre><code class="language-java">private Invocation.Builder getBuilder(WebTarget target, String token) {
   return target.request().header(&quot;Authorization&quot;, &quot;token &quot; + token);
}
</code></pre>
<p>Ok, now that we have those basic pieces in place, we can start requesting for real.</p>
<p>Let&#39;s get the basic user profile, for starters</p>
<p>First, we create a basic data structure that we&#39;ll use to deserialize the payload from Github. I&#39;ll skip most of the available fields here as they&#39;re not needed.</p>
<pre><code class="language-java">public class GithubOwner implements Serializable {

   public int id;
   public String name;
   public String login;
   public String email;
   public String avatar_url;
}
</code></pre>
<p>Now, you should all be yelling at me about those public fields. Let me remember you that this data structure is only used for deserializing purpose, it won&#39;t ever be used for anything else, so what&#39;s the point in complicating things?</p>
<p>Now let&#39;s get back to business, we have a way to construct authenticated requests, and a model in which to store the data. So let&#39;s do it!</p>
<p>First, let&#39;s get to the right endpoint: <code>/user</code></p>
<pre><code class="language-java">   getTarget().path(&quot;/user&quot;);
</code></pre>
<p>Now, let&#39;s actually issue the request, and get a response</p>
<pre><code class="language-java">   Response r = getBuilder(getTarget().path(&quot;/user&quot;), token).get();
</code></pre>
<p>Let&#39;s deserialize the data from github</p>
<pre><code class="language-java">   GithubOwner owner = mh.readValue(r.readEntity(String.class), GithubOwner.class);
</code></pre>
<p>And here we are, with some integrity checks added:</p>
<pre><code class="language-java">   public GithubOwner getSelf(String token) {
      Response r = getBuilder(getTarget().path(&quot;/user&quot;), token).get();
      if (r.getStatus() &lt; 300) {
         try {
            GithubOwner owner = mh.readValue(r.readEntity(String.class), GithubOwner.class);
            return owner;
         } catch (IOException e) {
            lh.log(GithubAPIHelper.class.getName(), Level.SEVERE, null, e);
         }
      }
      return null;
   }
</code></pre>
<h3 id="dealing-with-pagination">Dealing with pagination</h3>
<p>Getting the user&#39;s profile was quite easy and straightforward, but everything isn&#39;t that smooth.</p>
<p>Let&#39;s say we now want all the repositories, instinctively, here is what we&#39;d do:</p>
<pre><code class="language-java">public class GithubRepository implements Serializable {

   public long id;
   public String name;
   public String description;
   public GithubOwner owner;
   @JsonProperty(value = &quot;private&quot;)
   public boolean isPrivate;
   public String ssh_url;
   public String git_url;
}
</code></pre>
<pre><code class="language-java">   private TypeSafeList&lt;GithubRepository&gt; getSelfRepositories(String token) {
      TypeSafeList&lt;GithubRepository&gt; repos = new TypeSafeArrayList&lt;&gt;();
      Response r = getBuilder(getTarget().path(&quot;/user/repos&quot;), token).get();
      if (r.getStatus() &lt; 300) {
         try {
            List&lt;GithubRepository&gt; ms = mh.readValue(r.readEntity(String.class), new TypeReference&lt;List&lt;GithubRepository&gt;&gt;() {
            });
            repos.addAll(new TypeSafeArrayList&lt;&gt;(ms));
         } catch (IOException e) {
            lh.log(GithubAPIHelper.class.getName(), Level.SEVERE, null, e);
         }
      }
      return repos;
   }
</code></pre>
<p>That will actually work, but you won&#39;t get all of them, only the first 20 or so. If you want all of them, you&#39;ll have to follow the pagination.</p>
<p>First, we want to get the link marked as <code>rel=next</code> in the <code>Link</code> http header.</p>
<pre><code class="language-java">   private String getNextLink(Response r) {
      String link = r.getHeaderString(&quot;Link&quot;);   /* &lt;http://foobar&gt;; rel=&quot;next&quot;, &lt;http://blah/&gt;; rel=last */
      if (link != null) {
         String[] links = link.split(&quot;,&quot;);
         for (String l : links) {               /* &lt;http://foobar&gt;; rel=&quot;next&quot; */
            if (l.contains(&quot;rel=\&quot;next\&quot;&quot;)) {
               String[] tmp1 = l.split(&quot;&lt;&quot;, 2);
               if (tmp1.length == 2) {
                  return tmp1[1].split(&quot;&gt;&quot;, 2)[0];  /* http://foobar */
               }
            }
         }
      }
      return null;
   }
</code></pre>
<p>Next, we want to request this url and get the next data to our initial request</p>
<pre><code class="language-java">   private Response getNextData(Response r, String token) {
      String link = getNextLink(r);
      if (link == null)
         return null;
      return getBuilder(getClient().target(link), token).get();
   }
</code></pre>
<p>Now let&#39;s put all the pieces together, addind a loop to retrieve all the data</p>
<pre><code class="language-java">   private TypeSafeList&lt;GithubRepository&gt; getSelfRepositories(String token) {
      TypeSafeList&lt;GithubRepository&gt; repos = new TypeSafeArrayList&lt;&gt;();
      Response r = getBuilder(getTarget().path(&quot;/user/repos&quot;), token).get();
      while (r != null) {
         if (r.getStatus() &lt; 300) {
            try {
               List&lt;GithubRepository&gt; ms = mh.readValue(r.readEntity(String.class), newhTypeReference&lt;List&lt;GithubRepository&gt;&gt;() {
               });
               repos.addAll(new TypeSafeArrayList&lt;&gt;(ms));
            } catch (IOException e) {
               lh.log(GithubAPIHelper.class.getName(), Level.SEVERE, null, e);
            }
         }
         r = getNextData(r, token);
      }
      return repos;
   }
</code></pre>
<p>And voila, you now have a working Github HTTP client. Once you got these, the other endpoints are really easy.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I learned Scala in one month</title>
		<link>https://stagingv6.cleverapps.io/blog/engineering/2015/03/20/getting-started-with-scala/</link>
		
		<dc:creator><![CDATA[Leonard Imbert]]></dc:creator>
		<pubDate>Fri, 20 Mar 2015 15:32:00 +0000</pubDate>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Scala]]></category>
		<category><![CDATA[tutorial]]></category>
		<guid isPermaLink="false">https://www2.cleverapps.io/wp/blog/technology/2015/03/20/getting-started-with-scala/</guid>

					<description><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>Hi, I’m Leonard. I have been an intern developer at Clever Cloud for one month now. When I came in, the CEO put me on a Scala project the first day. As a software engineer, there’s often a pressure to know everything, and I had never done scala before. My only experience in programming was html, php, javascript, and a little bit  of java. So I had to dive into this new language quite quickly.</p>
<span id="more-2795"></span>

<p>The thing is, Scala is a functional programming language. And the most brutal change was to learn this new paradigm. If you don&#39;t know what functional programming is, there is something you need to understand. In FP, the trick is to do everything only with functions (as in math function). Define the purest function that you can.</p>
<p>But you&#39;ll ask me, what is the interest of a pure function? A pure function is very useful because it can be tested separately, and especially because it&#39;s very reusable!</p>
<center>
  <figure>
    <img src="https://www2.cleverapps.io/app/uploads/2021/08/skyrim-vahala.gif">
    <figcaption>First steps towards the infinite beauty of pure functions</figcaption>
  </figure>
</center>

<h3 id="whats-a-pure-function">What’s a pure function?</h3>
<p>A pure function takes a value, returns an other value and does nothing else. For a given argument, it always returns the same result.  You don&#39;t want any side effect like database calls, etc. But there’s some help from the compiler: Scala has a strong static type system. Be sure the compiler will yell at you if you try to bypass it.</p>
<p>At first sight, Scala can look like an awful programming language, especially if you only code in javascript or php. But after a couple of weeks, by trying hard and being bashed a lot by the compiler, your code gets more and more structured. You finally get used to pure functions, and employ less and less side effects and mutating values.</p>
<p>After one month, I did not become a professional in Scala, but I’m now more and more comfortable with it and I find pleasure in coding. I began to integrate the abilities of FP principles and their great potential. Think about all the possibilities it can offer: it is almost endless.</p>
<h3 id="getting-started-with-scala">Getting started with Scala</h3>
<p>To learn scala, it’s useful to have some tooling in order to evaluate your code. Check the <a href="http://scala-lang.org">download page</a> to get typesafe activator. If you have a favorite IDE, I recommend to keep it. Else I personally use vim or sublime text, where Scala syntax highlighting works out of the box.</p>
<p>First, there is more than one way to learn scala. A good way is to look at concrete exercises. Try to rewrite a basic mathematical function or some exercises like this one.</p>
<p>&quot;I have x employees in my office. I want to have the sum of the salary of all Senior employees&quot;</p>
<p>First we need to create the <code>Employee</code> class</p>
<pre><code class="language-scala">case class Employee(name: String, title: String, salary: Int)
</code></pre>
<p>Then we create a list of these salary</p>
<pre><code class="language-scala">val employees: List[Employee] = List(
  Employee(&quot;Smith&quot;, &quot;Junior Developer&quot;, 1250),
  Employee(&quot;George&quot;, &quot;Senior Analyst&quot;, 2000),
  Employee(&quot;David&quot;, &quot;Cadet Developer&quot;, 1000),
  Employee(&quot;Bernard&quot;, &quot;Senior Developer&quot;, 2100),
  Employee(&quot;Clement&quot;, &quot;Senior Developer&quot;, 1850)
)
</code></pre>
<p>I then define a function which takes an <code>Employee</code> as a parameter, and returns true if the employee title begins with &quot;Senior&quot;.</p>
<pre><code class="language-scala">def isSenior(employee: Employee) = employee.title.startsWith(&quot;Senior&quot;)
</code></pre>
<p>Finally, we just apply <code>isSenior</code> on the list of employees to keep the senior employees, and then sum their salaries.</p>
<pre><code class="language-scala">val seniorSalaries =
   employees
     .filter(isSenior _)
     .map(_.salary)
     .sum
</code></pre>
<p>To explain, we apply the <code>filter</code> method to our list. <code>filter</code> is a native function which selects all elements which satisfy a predicate (here the <code>isSenior</code> function). Then we map over it. <code>map</code> transforms a list of elements of type A into a list of elements of type B, by applying a function from A to B to all its elements. Here, we transform a <code>List[Employee]</code> into a <code>List[Int]</code> by getting the salary of each employee. Finally, we do a sum on the list of salaries.</p>
<p>As you can see, we solved the problem with small pure functions. They are reusable regardless of the context and we were able to compose them with functions provided by the scala standard library.</p>
<p>If you want to dig deeper into Scala, check this <a href="http://manning.com/bjarnason/">book</a></p>
<p>If you have any questions, don’t hesitate to send me an email at <a href="mailto:&#108;&#101;&#111;&#x6e;&#97;&#114;&#100;&#46;&#105;&#x6d;&#98;&#101;&#x72;&#116;&#64;&#99;&#x6c;&#101;&#118;&#101;&#114;&#x2d;&#x63;&#108;&#111;&#117;&#x64;&#46;&#x63;&#x6f;&#x6d;">&#108;&#101;&#111;&#x6e;&#97;&#114;&#100;&#46;&#105;&#x6d;&#98;&#101;&#x72;&#116;&#64;&#99;&#x6c;&#101;&#118;&#101;&#114;&#x2d;&#x63;&#108;&#111;&#117;&#x64;&#46;&#x63;&#x6f;&#x6d;</a></p>
]]></description>
										<content:encoded><![CDATA[<p><img width="1400" height="540" src="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1.png" class="attachment-post-thumbnail size-post-thumbnail wp-post-image" alt="" decoding="async" loading="lazy" srcset="https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1.png 1400w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1-300x116.png 300w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1-1024x395.png 1024w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1-768x296.png 768w, https://staging-cc-assetsv6.cellar-c2.services.clever-cloud.com/uploads/2021/08/getting-started-scala-1-1368x528.png 1368w" sizes="auto, (max-width: 1400px) 100vw, 1400px" /></p><p>Hi, I’m Leonard. I have been an intern developer at Clever Cloud for one month now. When I came in, the CEO put me on a Scala project the first day. As a software engineer, there’s often a pressure to know everything, and I had never done scala before. My only experience in programming was html, php, javascript, and a little bit  of java. So I had to dive into this new language quite quickly.</p>
<span id="more-2795"></span>

<p>The thing is, Scala is a functional programming language. And the most brutal change was to learn this new paradigm. If you don&#39;t know what functional programming is, there is something you need to understand. In FP, the trick is to do everything only with functions (as in math function). Define the purest function that you can.</p>
<p>But you&#39;ll ask me, what is the interest of a pure function? A pure function is very useful because it can be tested separately, and especially because it&#39;s very reusable!</p>
<center>
  <figure>
    <img src="https://www2.cleverapps.io/app/uploads/2021/08/skyrim-vahala.gif">
    <figcaption>First steps towards the infinite beauty of pure functions</figcaption>
  </figure>
</center>

<h3 id="whats-a-pure-function">What’s a pure function?</h3>
<p>A pure function takes a value, returns an other value and does nothing else. For a given argument, it always returns the same result.  You don&#39;t want any side effect like database calls, etc. But there’s some help from the compiler: Scala has a strong static type system. Be sure the compiler will yell at you if you try to bypass it.</p>
<p>At first sight, Scala can look like an awful programming language, especially if you only code in javascript or php. But after a couple of weeks, by trying hard and being bashed a lot by the compiler, your code gets more and more structured. You finally get used to pure functions, and employ less and less side effects and mutating values.</p>
<p>After one month, I did not become a professional in Scala, but I’m now more and more comfortable with it and I find pleasure in coding. I began to integrate the abilities of FP principles and their great potential. Think about all the possibilities it can offer: it is almost endless.</p>
<h3 id="getting-started-with-scala">Getting started with Scala</h3>
<p>To learn scala, it’s useful to have some tooling in order to evaluate your code. Check the <a href="http://scala-lang.org">download page</a> to get typesafe activator. If you have a favorite IDE, I recommend to keep it. Else I personally use vim or sublime text, where Scala syntax highlighting works out of the box.</p>
<p>First, there is more than one way to learn scala. A good way is to look at concrete exercises. Try to rewrite a basic mathematical function or some exercises like this one.</p>
<p>&quot;I have x employees in my office. I want to have the sum of the salary of all Senior employees&quot;</p>
<p>First we need to create the <code>Employee</code> class</p>
<pre><code class="language-scala">case class Employee(name: String, title: String, salary: Int)
</code></pre>
<p>Then we create a list of these salary</p>
<pre><code class="language-scala">val employees: List[Employee] = List(
  Employee(&quot;Smith&quot;, &quot;Junior Developer&quot;, 1250),
  Employee(&quot;George&quot;, &quot;Senior Analyst&quot;, 2000),
  Employee(&quot;David&quot;, &quot;Cadet Developer&quot;, 1000),
  Employee(&quot;Bernard&quot;, &quot;Senior Developer&quot;, 2100),
  Employee(&quot;Clement&quot;, &quot;Senior Developer&quot;, 1850)
)
</code></pre>
<p>I then define a function which takes an <code>Employee</code> as a parameter, and returns true if the employee title begins with &quot;Senior&quot;.</p>
<pre><code class="language-scala">def isSenior(employee: Employee) = employee.title.startsWith(&quot;Senior&quot;)
</code></pre>
<p>Finally, we just apply <code>isSenior</code> on the list of employees to keep the senior employees, and then sum their salaries.</p>
<pre><code class="language-scala">val seniorSalaries =
   employees
     .filter(isSenior _)
     .map(_.salary)
     .sum
</code></pre>
<p>To explain, we apply the <code>filter</code> method to our list. <code>filter</code> is a native function which selects all elements which satisfy a predicate (here the <code>isSenior</code> function). Then we map over it. <code>map</code> transforms a list of elements of type A into a list of elements of type B, by applying a function from A to B to all its elements. Here, we transform a <code>List[Employee]</code> into a <code>List[Int]</code> by getting the salary of each employee. Finally, we do a sum on the list of salaries.</p>
<p>As you can see, we solved the problem with small pure functions. They are reusable regardless of the context and we were able to compose them with functions provided by the scala standard library.</p>
<p>If you want to dig deeper into Scala, check this <a href="http://manning.com/bjarnason/">book</a></p>
<p>If you have any questions, don’t hesitate to send me an email at <a href="mailto:&#108;&#101;&#111;&#x6e;&#97;&#114;&#100;&#46;&#105;&#x6d;&#98;&#101;&#x72;&#116;&#64;&#99;&#x6c;&#101;&#118;&#101;&#114;&#x2d;&#x63;&#108;&#111;&#117;&#x64;&#46;&#x63;&#x6f;&#x6d;">&#108;&#101;&#111;&#x6e;&#97;&#114;&#100;&#46;&#105;&#x6d;&#98;&#101;&#x72;&#116;&#64;&#99;&#x6c;&#101;&#118;&#101;&#114;&#x2d;&#x63;&#108;&#111;&#117;&#x64;&#46;&#x63;&#x6f;&#x6d;</a></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
