Developer Blog

Tipps und Tricks für Entwickler und IT-Interessierte

Scrimba: JavaScript Advent Calendar

Solutions for the Scrimba JavaScriptmas Challenge

Day 24: Test Your Agility!

var pushed = false //Has the stop button been pushed - false is default
var targetInt; //The target number to stop the wheel on
var spinningElem = document.getElementById('spinning'); //The spinning number


const maxLoop = 10;
const waitTime = 250;

//event listener
document.getElementById("buttonPressed").addEventListener("click", buttonPressed);

//When the stop button is pushed
function buttonPressed(){
    pushed = true;
}

//set the target Int
function setTargetInt(){
    var targetElem = document.getElementById('targetNum');
    targetInt=Math.floor(Math.random() * (maxLoop + 1))
    targetElem.innerHTML = targetInt;
}

//sleep const
const sleep = (milliseconds) => {
  return new Promise(resolve => setTimeout(resolve, milliseconds))
}


var curr_spin=-1;

//EDIT THIS FUNCTION
const spin = async () => {
    var spinningElem = document.getElementById('spinning');
    for(let spin=0; spin < maxLoop; spin++) {
        spinningElem.innerHTML = spin;
        console.log('spin:', spin, targetInt, curr_spin)

        if (!pushed) {
            //
        } else if (spin == targetInt) {
            console.log('Button pushed and won')
             var result = document.getElementById('result');
            result.innerText = "WON!";
            spin = maxLoop+1;
        } else {
            console.log('Buitton pushed but missed')
            spin = maxLoop+1;
        }
        
        await sleep(waitTime)
    }
}

//main
setTargetInt();
spin();

Day 23: Social media input challenge

<html>
    <head>
        <link rel="stylesheet" href="index.css">
    </head>
    <body>
        <div class="container">
            <textarea type="text" id="tweet" placeholder="Type in the box"></textarea>
            <div id="counterFooter">140/140</div>
            <button id="btn"><h2>Tweet</h2></button>
        </div>
        <script src="index.js"></script>
    </body>
</html>
body{
  background-color: #023F6A;
  font-family: sans-serif;
}
.container{
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}
textarea{
  width:50%;
  height: 30vh;
  background-color: rgb(21, 32, 43);
  color: #fff;
  border-radius:10px;
}
textarea::placeholder{
    color:#fff;
}
#counterFooter {
  margin-top: 0.2rem;
  font-size:0.8rem;
  color: #fff;
  margin-left:30%;
  font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
button{
  width:50%;
  background-color: rgb(29, 161, 242);
  border-radius: 10px;
  padding: 0 10%;
}
.tweetRed {
    color: red;
}
button h2{
    color: #fff;
}
.buttonDisabled {
   opacity: .5;
   cursor: default;
}
const counter = document.getElementById('counterFooter');
const button = document.getElementById('btn');
function updateState() {
    const nrOfChar = 140 - tweet.value.length;
    
    counter.innerText = nrOfChar + '/140';
    
    (nrOfChar < 20) ? tweet.classList.add("tweetRed") : tweet.classList.remove("tweetRed");    
    (nrOfChar <  0) ? btn.classList.add("buttonDisabled") : btn.classList.remove("buttonDisabled");
}
function handleKeyUp(event) {
    updateState()
}
tweet.addEventListener('keyup', handleKeyUp);
updateState()

Day 22: Extract Matrix Column

function extractMatrixColumn(matrix, column) {
    let extracted = []
    
    matrix.forEach( row => {
        extracted.push(row[column])
    })
    
    return extracted;
}
function extractMatrixColumn(matrix, column) {   
    return matrix.map( row => row[column])
}

Day 21: Sum of 2

function sumOfTwo(nums1, nums2, value) {
    let result = false;
    
    nums1.forEach( num1 => {
        nums2.forEach( num2 => {            
            if ( (num1 + num2) === value) {
                result = true;
            }
        })
    })
    return result;
}

Day 20: Domain Type

function domainType(domains) {
    map = { "org": "organization",
            "com": "commercial", 
            "net": "network",
            "info":  "information"
    }
    
    types=[]    
    
    domains.forEach( (domain) => {
        last = domain.split('.').slice(-1)[0]
        
        types.push(map[last])
    })
    
    return types
}

Day 19: Alpahabet Subsequence

function alphabetSubsequence(str) {
    chars = str.split("")
    
    result=true
    for(pos=1; pos<chars.length; pos++) {       
        result = result && chars[pos-1] < chars[pos] 
    }
    return result
}

Day 18: Array previous less

function arrayPreviousLess(nums) {
    let result = [];
    let temp=[];
    
    for(indx=0; indx < nums.length; indx++) {
        curr = nums[indx];
        
        // Build array with previous values
        temp.push(curr)
        
        // Find previous values less than current value
        mins = temp.filter( (val) => val < curr)
        
        // Return value at most right
        max = (mins.length == 0) ? -1 : max = mins[mins.length-1];
        
        result.push(max);
    }
    
    return result;
}

Day 17: Different symbols naive

function differentSymbolsNaive(str) {
    m={};
    
    n=0;
    str.split("").sort().forEach( (c) => {                
        if (! (c in m)) n++;
        m[c]=1;
    });
        
    return n
}

Day 16: Insert dashes

function insertDashes(arr) {
    return arr.split(" ").map( part =>part.split("").join("-") ).join(" ");
}

Day 15: Javascript Carousel

function getIndexOfCurrent(tags) {
	let result = -1;
	tags.forEach((node, indx) => {
		if (node.classList.contains('curr')) {
			result = indx;
		}
	});
	return result;
}
function move(dir) {
	var tags = Array.prototype.slice.call(
		document.getElementsByClassName('card')
	);
	let curr = getIndexOfCurrent(tags);
	if (dir === 'prev') {
		next = curr === 0 ? 0 : curr - 1;
	}
	if (dir === 'next') {
		next = curr === tags.length - 1 ? tags.length - 1 : curr + 1;
	}
	tags[curr].setAttribute('class', 'card last');
	tags[next].setAttribute('class', 'card curr');
}
<html>
    <head>
        <link rel="stylesheet" href="index.css">
    </head>
    <body>
        
        <div class="container">
            <img src="previous.svg" class="previous" alt="previous image">
            <div class="gallery-wrapper">
                <div class="gallery">
                    <img class="card curr" src="presents.jpg" alt="Christmas Cookies">
                    <img class="card" src="cookies.jpg" alt="Christmas Cookies">
                    <img class="card" src="santa.jpg" alt="Christmas Cookies">
                    <img class="card" src="candycane.jpg" alt="Christmas Cookies">
                    <img class="card" src="reindeer.jpg" alt="Christmas Cookies">
                </div>
            </div>
            <img src="next.svg" class="next" alt="next image">
        
        </div>
        
        <script src="index.pack.js"></script>
    
    </body>
</html>
/*
Thanks to these fine individuals from Unsplash:
https://unsplash.com/photos/AmzKuEnr1VY
https://unsplash.com/photos/eDnJQL21amc
https://unsplash.com/photos/LXy2DOOxESQ
https://unsplash.com/photos/KBKHXjhVQVM
https://unsplash.com/photos/PxM8aeJbzvk
*/
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@600&display=swap');
html,
body {
	margin: 0;
	padding: 0;
	height: 100vh;
	font-family: 'Playfair Display';
	display: grid;
	justify-content: center;
}
img {
	width: 200px;
}
.previous,
.next {
	width: 35px;
	justify-self: center;
	align-self: center;
	cursor: pointer;
}
.previous {
	opacity: 0.3;
}
.container {
	display: grid;
	grid-template-columns: 20% 200px 20%;
	place-content: center;
}
.card {
	width: 100%;
	display: none;
}
.curr {
	display: block;
}
.curr {
	animation-duration: 5s;
	animation-name: slideIn;
}
.last {
	animation-duration: 2s;
	animation-name: slideOut;
}
@keyframes slideOut {
	from { opacity: 1; }
	to   { opacity: 0; }
}
@keyframes slideIn {
	from { opacity: 0; }
	to   { opacity: 1; }
}

Day 14: Maximal Adjacent Difference

    let result=0, max=0, val1=0, val2=0;
    
    for(pos=0; pos < nums.length; pos++) {
        
        [val1, val2 ] = [ nums[pos], nums[pos+1] ];
        max = (val1 > val2) ? (val1 - val2) : (val2 - val1);
        
        if (max > result) {
            result = max;
        }
    }
     
    return result;
}

Day 13: Extract Eacth Kth

function extractEachKth(nums, kth) {
    return nums.filter( (value, index) => (index+1)
}

Day 12: Valid Time

Number.prototype.between = function(min, max) {
  return this > min && this < max;
};
function validTime(str) {
    const parts = str.split(':')
   
    return parseInt(parts[0]).between(0,24) && parseInt(parts[1]).between(0,59);
}

Day 11: Avoid Obstacles

function avoidObstacles(nums) {
    const sorted = nums.sort();
        
    for(num=2; num <= sorted[nums.length-1]; num++) {
        match = nums.filter((val) => (val
        if (match.length === 0) {
            return num;
        }
    }
}

Day 10: Adjacent Elements Product

function adjacentElementsProduct(nums) {
    let result = 0;
    
    for (i1 = 0; i1 < nums.length-1; ++i1) {
        const product=nums[i1]*nums[i1+1];
                 
        if (product > result) {
            result = product;
        }
    }
    
    return result;
}

Day 09: Sum Odd Fibonacci Numbers

function sumOddFibonacciNumbers(num) {
    let fibPrev=1;
    let fib=0;
    let sum=0;
    
    while (fibPrev < num) {       
        [ fibPrev, fib ] = [fib + fibPrev, fibPrev];
        
        if (fib
            sum += fib;
        }
    }
    
    return sum;
}

Day 08: Rolling Dice

<html>
    <head>
        <link rel="stylesheet" href="style.css">
        <script src="index.pack.js"></script>
    </head>
    <body>
        <div class="dice">
            <div class="dot dot_ dot2 dot_ dot4 dot5 dot6"></div>
            <div class="dot dot_ dot_ dot_ dot_ dot_ dot_"></div>
            <div class="dot dot_ dot_ dot3 dot4 dot5 dot6"></div>
            
            <div class="dot dot_ dot_ dot_ dot_ dot_ dot6"></div>
            <div class="dot dot1 dot_ dot3 dot_ dot5 dot_"></div>
            <div class="dot                          dot6"></div>
            
            <div class="dot dot_ dot_ dot3 dot4 dot5 dot6"></div>
            <div class="dot"></div>
            <div class="dot dot_ dot2 dot_ dot4 dot5 dot6"></div>
        </div>
        
    </body>
</html>
function clear_dice() {
    document.querySelectorAll('.dot').forEach( (dot) => dot.style.visibility = "hidden")
}
function roll_dice() {
    const roll = 1 + Math.floor(Math.random() * 6);
    
    console.log(roll);
    clear_dice()
    document.querySelectorAll('.dot'+roll).forEach( (dot) => {
        dot.style.visibility = "visible"
    })
}
clear_dice()
document.getElementsByClassName('dice')[0].addEventListener('click', roll_dice)
body {
    background-color: #AEB8FE;
    display: flex;
}
.dice {
    width: 230px;
    height: 230px;
    border-radius: 10px;
    background-color: #EFE5DC;
    margin: 100px;
    
    display: grid;
    grid-template-columns: repeat(3, 40px);
    gap: 20px;
    grid-auto-rows: minmax(40px, 40px);
}
.dot {
    width: 40px;
    height: 40px;
    border-radius: 15px;
    background-color: black;
    margin: 35px;
    
    visibility: hidden
}
.dot1 { visibility: none; }
.dot2 { visibility: none; }
.dot3 { visibility: none; }
.dot4 { visibility: none; }
.dot5 { visibility: none; }
.dot6 { visibility: none; }

Day 07: Count Vowel Consonant

function countVowelConsonant(str) {
  function reducer(s,c) {
      return s + ("aeiou".includes(c) ? 1 : 2)
  };
    
  return str.split("").reduce(reducer, 0)
}

Day 06: Sort By Length

function sortByLength(strs) {    
    return strs.sort(function(arg1, arg2) { return arg1.length - arg2.length })
}

Day 05: Reverse String

function reverseAString(str) {   
    return str.split("").reverse().join("")
}

Day 04: Century From Year

function centuryFromYear(num) {
    return Math.floor((num + 99) / 100)
}

Day 03: Chunky Monkey

function chunkyMonkey(values, size) {
    result = [];
    pos = 0;
    
    while (pos < values.length) {
        result.push(values.slice(pos, pos+size));
        pos += size;
    }
    
    return result;
}

Day 02: Deposit Profit

function depositProfit(deposit, rate, threshold) {
    let profit = deposit;
    let years = 0
    while (profit < threshold) {
        profit += profit * 0.01 * rate;
        years++;
    }
    
    return years;
}

Day 01: Candies

https://scrimba.com/learn/adventcalendar/note-at-0-00-coef0430d83cd2a72113bbf09

function candies(children, candy) {
    return children * Math.floor(candy / children)//  write code here.
}

Keycloak | Getting Started

Introduction

Keycloak – Open Source Identity and Access Management for Modern Applications and Services

Installation

Java

Using AdoptOpenJDK8

brew info adoptopenjdk8

Eclipse

Keycloak

WildFly

See Also

Troubleshooting

Change Server Port

By default, executing standalone.sh (for Linux) / standalone.bat (for Windows) makes the server available at following urls:

https://localhost:8443/auth/
http://localhost:8080/auth/

If we need to run multiple instance of server at different ports, run the following command:

For Linux:

standalone.sh -Djboss.socket.binding.port-offset=100

For Windows:

standalone.bat -Djboss.socket.binding.port-offset=100

The above commands will add the offset of 100 to the defaults ports available for Keycloak server.

For example, previously the ports where 8443 and 8000. Now the new ports become 8443 + 100 = 8543 and 8080 + 100 = 8180.

References:

https://www.keycloak.org/docs/3.2/getting_started/topics/secure-jboss-app/before.html

Location of Server Logfile

\standalone\log

Additional Readings

Maven | Getting Started

Introduction

Installation

Install on macOS

$ brew install maven

Maven Commands

Maven Commands

Let’s look into some popular and must know maven commands. We will use a sample Maven project to showcase the command output.

1. mvn clean

This command cleans the maven project by deleting the target directory. The command output relevant messages are shown below.

$ mvn clean
...
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ maven-example-jar ---
[INFO] Deleting /Users/pankaj/Desktop/maven-examples/maven-example-jar/target
...
2. mvn compiler:compile

This command compiles the java source classes of the maven project.

$ mvn compiler:compile
...
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-cli) @ maven-example-jar ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/pankaj/Desktop/maven-examples/maven-example-jar/target/classes
...

3. mvn compiler:testCompile

This command compiles the test classes of the maven project.

$ mvn compiler:testCompile
...
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-cli) @ maven-example-jar ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/pankaj/Desktop/maven-examples/maven-example-jar/target/test-classes
...

4. mvn package

This command builds the maven project and packages them into a JAR, WAR, etc.

$ mvn package
...
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ maven-example-jar ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/pankaj/Desktop/maven-examples/maven-example-jar/target/classes
...
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.journaldev.maven.classes.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec

Results :
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[INFO] 
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ maven-example-jar ---
[INFO] Building jar: .../maven-examples/maven-example-jar/target/maven-example-jar-0.0.1-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
...

The output shows the location of the JAR file just before the “BUILD SUCCESS” message. Notice the package goal executes compile, testCompile, and test goals before packaging the build.

5. mvn install

This command builds the maven project and installs the project files (JAR, WAR, pom.xml, etc) to the local repository.

$ mvn install
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ maven-example-jar ---
...
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ maven-example-jar ---
...

6. mvn deploy

This command is used to deploy the artifact to the remote repository. The remote repository should be configured properly in the project pom.xml file distributionManagement tag. The server entries in the maven settings.xml file is used to provide authentication details.

7. mvn validate

This command validates the maven project that everything is correct and all the necessary information is available.

8. mvn dependency:tree

This command generates the dependency tree of the maven project.

$ mvn dependency:tree
...
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.journaldev.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.platform:junit-platform-runner:jar:1.2.0:test
[INFO] |  +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] |  +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
...

9. mvn dependency:analyze

This command analyzes the maven project to identify the unused declared and used undeclared dependencies. It’s useful in reducing the build size by identifying the unused dependencies and then remove it from the pom.xml file.

$ mvn dependency:analyze
...
[INFO] --- maven-dependency-plugin:2.8:analyze (default-cli) @ Mockito-Examples ---
[WARNING] Used undeclared dependencies found:
[WARNING]    org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
[WARNING]    org.mockito:mockito-core:jar:2.19.0:test
[WARNING] Unused declared dependencies found:
[WARNING]    org.junit.platform:junit-platform-runner:jar:1.2.0:test
...

10. mvn archetype:generate

Maven archetypes is a maven project templating toolkit. We can use this command to generate a skeleton maven project of different types, such as JAR, web application, maven site, etc.

Recommended Reading: Creating a Java Project using Maven Archetypes

11. mvn site:site

This command generates a site for the project. You will notice a “site” directory in the target after executing this command. There will be multiple HTML files inside the site directory that provides information related to the project.

12. mvn test

This command is used to run the test cases of the project using the maven-surefire-plugin.

$ mvn test
...
[INFO] --- maven-surefire-plugin:2.22.0:test (default-test) @ Mockito-Examples ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
[INFO] Running TestSuite
first-element
second-element
Employee setName Argument = Pankaj
...
[INFO] Results:
[INFO] 
[INFO] Tests run: 5, Failures: 0, Errors: 0, Skipped: 0
...

13. mvn compile

It’s used to compile the source Java classes of the project.

$ mvn compile
...
[INFO] --- maven-compiler-plugin:3.7.0:compile (default-compile) @ Mockito-Examples ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 10 source files to /Users/pankaj/Desktop/maven-examples/Mockito-Examples/target/classes
...

14. mvn verify

This command build the project, runs all the test cases and run any checks on the results of the integration tests to ensure quality criteria are met.

Maven Options

Maven provides a lot of command-line options to alter the maven build process. Let’s look at some of the important maven options.

15. mvn -help

This command prints the maven usage and all the available options for us to use.

16. mvn -f maven-example-jar/pom.xml package

This command is used to build a project from a different location. We are providing the pom.xml file location to build the project. It’s useful when you have to run a maven build from a script.

17. mvn -o package

This command is used to run the maven build in the offline mode. It’s useful when we have all the required JARs download in the local repository and we don’t want Maven to look for any JARs in the remote repository.

18. mvn -q package

Runs the maven build in the quiet mode, only the test cases results and errors are displayed.

$ mvn -q package         

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.journaldev.maven.classes.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.006 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

19. mvn -X package

Prints the maven version and runs the build in the debug mode. It’s opposite of the quiet mode and you will see a lot of debug messages in the console.

mvn -X Debug Mode

20. mvn -v

Used to display the maven version information.

$ mvn -v
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: /Users/pankaj/Downloads/apache-maven-3.6.3
Java version: 13.0.1, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-13.0.1.jdk/Contents/Home
Default locale: en_IN, platform encoding: UTF-8
OS name: "mac os x", version: "10.15.1", arch: "x86_64", family: "mac"

21. mvn -V package

This command prints the maven version and then continue with the build. It’s equivalent to the commands mvn -v;mvn package.

22. mvn -DskipTests package

The skipTests system property is used to skip the unit test cases from the build cycle. We can also use -Dmaven.test.skip=true to skip the test cases execution.

23. mvn -T 4 package

This command tells maven to run parallel builds using the specified thread count. It’s useful in multiple module projects where modules can be built in parallel. It can reduce the build time of the project.

See also

Trobleshooting

Could not find or load main class org.apache.maven.wrapper.MavenWrapperMain

You’re missing the .mvn folder in your git repository. You should have a folder called .mvn which contains the following files

  • wrapper/maven-wrapper.jarwrapper/maven-wrapper.properties
  • jvm.config.

Try doing git add -f .mvn from the command line then commit and push.

Here is how to create .mvn directory with needed jar inside.

mvn -N io.takari:maven:wrapper

We can also specify the version of Maven:

mvn -N io.takari:maven:wrapper -Dmaven=3.5.2

Java | Getting Started

Introduction

Installation

Install on macOS

$ brew tap adoptopenjdk/openjdk

Java 8

# Install Java 8
$ brew cask install adoptopenjdk8

# Install Java 11
$ brew cask install adoptopenjdk11
# Install Gradle
$ brew install gradle

# Install Maven
$ brew install maven

Managing different Version

Install jenv and setup

$ brew install jenv

Add java home folder to jenv

$ jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home
$ jenv add /Library/Java/JavaVirtualMachines/adoptopenjdk-11.jdk/Contents/Home

Spring Boot | Getting Started

Introduction

Spring makes programming Java quicker, easier, and safer for everybody. Spring’s focus on speed, simplicity, and productivity has made it the world’s most popular Java framework.

Required Software

Java

Spring recommend AdoptOpenJDK version 8 or version 11.

Oracle AdoptOpenJDK OpenJDK

Eclipse

Eclipse IDE for Enterprise Java Developers

Sprint Tools | 4

Spring Tools 4 for Eclipse

Create a new App from CLI

Create a starter app using spring.io from the commandline

$ curl https://start.spring.io/starter.zip -d language=java -d dependencies=web,mustache,jpa,h2,devtools -d packageName=com.example.blog -d name=Blog -o blog.zip

Working with Maven

Build App./mvnw clean package
Run App./mvnw spring-boot:run

Tipps and Tricks

Change App Port Number

Add line to file src/main/resources/application.properties

server.port=9010

Learning Path

Start with the following tutorials / guides:

See Also

Rust | Getting Started

Introduction

From Wikipedia, the free encyclopedia:

Rust is a multi-paradigm programming language focused on performance and safety, especially safe concurrency. Rust is syntactically similar to 

Rust was originally designed by Graydon Hoare at Mozilla Research.

It has gained increasing use in industry and is now Microsoft’s language of choice for secure and safety-critical software components.

Rust has been the “most loved programming language” in the Stack Overflow Developer Survey every year since 2016.

Rust could be used in different areas

Read more

Elixir| Einstieg in Elixir und Phoenix

Installation

Erlang / Elixir

Unter Windows

Installationspakete unter Erlang / Downloads (Version 24.0) und Elixir / Downloads (Web Installer)

Erstellen einer ersten Anwendung

Anwendung mit dem Namen ‘app’ erstellen.

Als Vorlage wird ‘live’ werwendet. Diese vewendet Phoenix.LiveView und erleichter die Erstellung von Web Anwendungen.

mix phx.new --live app

Frontend erstellen

cd app
cd assets 
npm install 
node node_modules/webpack/bin/webpack.js --mode development

Datenbank-Instanz einrichten und starten

Elixir und Phoenix verwendet in der Standardeinstellung eine PostgreSQL Datenbanken.

Der einfachste Weg, eine lauffähige PostgrSQL Datenbank einzurichten, ist mit Hilfe von Docker.

Erstellen Sie hierzu einen Datei docker-compose.yml:

version: '3.5'

networks:
  postgres:
    name: ${POSTGRES_CONTAINER:-workshop_elixir_postgres}
    driver: bridge

volumes:
    postgres:
      name: postgres

services:
  postgres:
    container_name: ${POSTGRES_CONTAINER:-workshop_elixir_postgres}
    image: postgres
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-postgres}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
      PGDATA: /data/postgres

    volumes:
       - postgres:/data/postgres

    ports:
      - "5432:5432"

    networks:
      - postgres

    restart: unless-stopped

Starten Sie die Datenbank in einem eigenen Fenster mit dem nachfolgenden Kommando:

docker compose up
[+] Running 14/14
 - db Pulled
   - b4d181a07f80 Already exists
   - 46ca1d02c28c Pull complete
   - a756866b5565 Pull complete
   - 36c49e539e90 Pull complete
   - 664019fbcaff Pull complete 
   - 727aeee9c480 Pull complete
   - 796589e6b223 Pull complete
   - 6664992e747d Pull complete
   - 0f933aa7ccec Pull complete
   - 99b5e5d88b32 Pull complete
   - a901b82e6004 Pull complete
   - 625fd35fd0f3 Pull complete
   - 9e37bf358a5d Pull complete
[+] Running 1/1
 - Container elixis_postgres  Started
Attaching to elixis_postgres
elixis_postgres  | The files belonging to this database system will be owned by user "postgres".
elixis_postgres  | This user must also own the server process.
...
...
...
elixis_postgres  | 2021-07-12 15:01:08.042 UTC [1] LOG:  database system is ready to accept connections

Datenbanktabellen erstellen

Festlegen der Datenbank-Verbindungsparameter in der Datei config/dev.exs.

Wir verwenden dabie die gleichen Werte, die wir in der Datei docker-compose.yml verwendet haben:

POSTGRES_USERusername
POSTGRES_PASSWORDpassword
POSTGRES_DBdatabase
config :app, App.Repo,
  username: "root",
  password: "root",
  database: "playground",
  hostname: "localhost",
  show_sensitive_data_on_connection_error: true,
  pool_size: 10

Erstellen der Datenbank-Tabellen

mix ecto.create

Webserver starten

mix phx.server

Links

Elixir und das Web

Elixir und Datenbanken

  • Ecto – domain specific language for writing queries and interacting with databases Github

Tips zum Erlernen von Elixir

Screencasts

Übungen /Exercises

Bücher

Cobol | Get Started

Installation

Cobol

brew install gnu-cobol
cobc --version
cobc (GnuCOBOL) 2.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Keisuke Nishida, Roger While, Ron Norman, Simon Sobisch, Edward Hart
Built     Oct 15 2019 14:14:21
Packaged  Sep 06 2017 18:48:43 UTC
C version "4.2.1 Compatible Apple LLVM 11.0.0 (clang-1100.0.33.8)"

First Steps

Create sample programm

Create Hello World programm hello_world.cob

HELLO * HISTORIC EXAMPLE OF HELLO WORLD IN COBOL
       IDENTIFICATION DIVISION.
       PROGRAM-ID. HELLO.
       PROCEDURE DIVISION.
           DISPLAY "HELLO, WORLD".
           STOP RUN.

Compile programm and build executable program

cobc -x hello_world.cob

Run programm

$ ./helloworld
HELLO, WORLD

Jenkins | Build and Deploy a Groovy App

Introduction

Using Jenkins as an automation server for your development, you can automate such repeating tasks as testing and deploying your app.

Starting with a sample Groovy App (a simple calculator) with tests, you will learn how to integrate your app in Jenkins and build a pipeline, so that Jenkins runs the desired tasks every time, you change the code.

Prepare the sources

Clone the sample repository from Github.

You should clone the demo repository into you demo account, because you may change some file during this post., and you will not get write permissions for the demo repository.

Also, clone the repository to your local machine to see what our demo app looks like.

$ git clone https://github.com/jenkins-toolbox/SampleApp_GroovyCalculator
Cloning into 'SampleApp_GroovyCalculator'...
remote: Enumerating objects: 194, done.
remote: Counting objects: 100% (194/194), done.
remote: Compressing objects: 100% (138/138), done.
remote: Total 194 (delta 44), reused 137 (delta 23), pack-reused 0
Receiving objects: 100% (194/194), 93.40 KiB | 817.00 KiB/s, done.
Resolving deltas: 100% (44/44), done.

Go into the new create folder

$ cd SampleApp_GroovyCalculator/
$ ls
Jenkinsfile      README.md        bin              build.gradle     gradlew          src
Makefile         SampleCalculator build            gradle           settings.gradle

The first task, Jenkins will do in our pipeline: build your app

$ ./gradlew build

Because it’s the first time you start gradlew, the required software will be downloaded:

First: the current Gradle Version (Gradle is the Build Tool used by Groovy Projects)

Downloading https://services.gradle.org/distributions/gradle-6.2.1-bin.zip
………10%………20%………30%……….40%………50%………60%……….70%………80%………90%……….100%

Welcome to Gradle 6.2.1!

Here are the highlights of this release:
 - Dependency checksum and signature verification
 - Shareable read-only dependency cache
 - Documentation links in deprecation messages

For more details see https://docs.gradle.org/6.2.1/release-notes.html

Starting a Gradle Daemon, 2 stopped Daemons could not be reused, use --status for details

After this, your app will be tested

> Task :test

Calculator02Spec > two plus two should equal four PASSED

Calculator01Spec > add: 2 + 3 PASSED

Calculator01Spec > subtract: 4 - 3 PASSED

Calculator01Spec > multiply: 2 * 3 PASSED

BUILD SUCCESSFUL in 34s
5 actionable tasks: 5 executed

Perform the build again

No download is required. The build is much quicker.

$ ./gradlew build

BUILD SUCCESSFUL in 1s
5 actionable tasks: 5 up-to-date

Now, test our app:

./gradlew clean test

> Task :test

Calculator02Spec > two plus two should equal four PASSED

Calculator01Spec > add: 2 + 3 PASSED

Calculator01Spec > subtract: 4 - 3 PASSED

Calculator01Spec > multiply: 2 * 3 PASSED

BUILD SUCCESSFUL in 4s
5 actionable tasks: 5 executed

Create a Jenkins Pipeline

Start by clicking on the BlueOcean menu item.

Hint: Blue Ocean is not installed with the default Jenkins installation.

You have to install the corresponding Plugins.

Select Manage JenkinsManage Plugins.

Then, select the tab Available and enter in the Filter box: Blue Ocean.

Install all plugins, that will be listed.

Next: Click on the New Pipeline to create your first Pipeline

Use the Item GitHub to specify, where our code is stored

Next, use your GitHub account.

Be sure, that you cloned the demo repository

Next, we select the demo repository SampleApp_GroovyCalculator

Click on Create Pipeline and after a few seconds, the pipeline is created.

Immediately after creating the pipeline, Jenkins is starting the pipeline and all steps included.

If everything went well, you see a positive status

Now, click on the pipeline (e.g. the text master or the status icon) and you will see the pipeline with all steps and their corresponding state.

If you, want to edit the pipeline, for example to add another step, like on the pencil in the header.

Click on Cancel to leave the Pipeline editor.

Hint: If you click on Save, all changes are pushed back to the repository and Jenkins starts the Pipeline again.

Run the Pipeline

If you want to run your pipeline, click on the rerun icon for your pipeline

Python | Working with Azure

First Step: Hello World Sample

The following steps at borrowed from the quick start tutorial.

Download sample repository

$ git clone https://github.com/Azure-Samples/python-docs-hello-world
$ cd python-docs-hello-world

Create virtual environment

$ python3 -m venv venv
$ source venv/bin/activate
$ pip install -r requirements.txt
$ export FLASK_APP=application.py
$ flask run

Login zu Azure

$ az login

Deploy to App Service

$ az webapp up --sku F1 -n azure-toolbox-flask-demo -l westeurope
webapp azure-toolbox-flask-demo doesn't exist
Creating Resource group 'xx_xx_Linux_westeurope' ...
Resource group creation complete
Creating AppServicePlan 'xx_asp_Linux_westeurope_0' ...
Creating webapp 'flask-demo' ...
Configuring default logging for the app, if not already enabled
Creating zip with contents of dir .../Working-with_Python ...
Getting scm site credentials for zip deployment
Starting zip deployment. This operation can take a while to complete ...
Deployment endpoint responded with status code 202
You can launch the app at http://via-internet-flask-demo.azurewebsites.net
{
  "URL": "http:/azure-toolbox-flask-demo.azurewebsites.net",
  "appserviceplan": "xx_asp_Linux_westeurope_0",
  "location": "westeurope",
  "name": "azure-toolbox--flask-demo",
  "os": "Linux",
  "resourcegroup": "xx_xx_Linux_westeurope",
  "runtime_version": "python|3.7",
  "runtime_version_detected": "-",
  "sku": "FREE",
  "src_path": ".../Working-with_Python"
}

Create Django App with PostgreSQL

Installation PostgreSQL on Mac OS

$ brew install postgres
==> Installing dependencies for postgresql: krb5
==> Installing postgresql dependency: krb5
...
==> Installing postgresql
...
==> Caveats
==> krb5
krb5 is keg-only, which means it was not symlinked into /usr/local, because macOS already provides this software and installing another version in
parallel can cause all kinds of trouble.

If you need to have krb5 first in your PATH run:
  echo 'export PATH="/usr/local/opt/krb5/bin:$PATH"' >> ~/.bash_profile
  echo 'export PATH="/usr/local/opt/krb5/sbin:$PATH"' >> ~/.bash_profile

For compilers to find krb5 you may need to set:
  export LDFLAGS="-L/usr/local/opt/krb5/lib"
  export CPPFLAGS="-I/usr/local/opt/krb5/include"

For pkg-config to find krb5 you may need to set:
  export PKG_CONFIG_PATH="/usr/local/opt/krb5/lib/pkgconfig"

==> postgresql
To migrate existing data from a previous major version of PostgreSQL run:
  brew postgresql-upgrade-database

To have launchd start postgresql now and restart at login:
  brew services start postgresql
Or, if you don't want/need a background service you can just run:
  pg_ctl -D /usr/local/var/postgres start

Set user and passwords for postgres database

Create database and user for django app

$ psql postgres
psql (12.1)
Type "help" for help.

postgres=# CREATE DATABASE pollsdb;
CREATE DATABASE
postgres=# CREATE USER manager WITH PASSWORD '########';
CREATE ROLE
postgres=# GRANT ALL PRIVILEGES ON DATABASE pollsdb TO manager;
GRANT

Download sample repository

$ git clone https://github.com/Azure-Samples/djangoapp.git
$ cd djangoapp

Create virtual environment

$ python3 -m venv venv
$ source venv/bin/activate
$ pip install -r requirements.txt
$ cat env.sh
export DBHOST="localhost"
export DBUSER="manager"
export DBNAME="pollsdb"
export DBPASS="supersecretpass"
$ . env.sh
$ python manage.py  makemigrations
No changes detected
$ python manage.py  migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying polls.0001_initial... OK
  Applying sessions.0001_initial... OK
 $ python manage.py createsuperuser
Username (leave blank to use 'user'): admin
Email address: admin@localhost
Password:
Password (again):
Superuser created successfully.

Run server and acccess web page at http://127.0.0.1:8000/

$ python manage.py runserver
Performing system checks...

System check identified no issues (0 silenced).
January 25, 2020 - 16:42:14
Django version 2.1.2, using settings 'azuresite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[25/Jan/2020 16:42:26] "GET / HTTP/1.1" 200 111
[25/Jan/2020 16:42:26] "GET /static/polls/style.css HTTP/1.1" 200 27
Not Found: /favicon.ico
[25/Jan/2020 16:42:26] "GET /favicon.ico HTTP/1.1" 404 2688

Login zu Azure

$ az login

Deploy to App Service

$ az webapp up --sku F1 -n azure-toolbox-django-demo -l westeurope
webapp azure-toolbox-django-demo doesn't exist
Creating Resource group 'xx_xx_Linux_westeurope' ...
Resource group creation complete
Creating AppServicePlan 'xx_asp_Linux_westeurope_0' ...
Creating webapp 'flask-demo' ...
Configuring default logging for the app, if not already enabled
Creating zip with contents of dir .../Working-with_Django ...
Getting scm site credentials for zip deployment
Starting zip deployment. This operation can take a while to complete ...
Deployment endpoint responded with status code 202
You can launch the app at http://via-internet-django-demo.azurewebsites.net
{
  "URL": "http:/azure-toolbox-django-demo.azurewebsites.net",
  "appserviceplan": "xx_asp_Linux_westeurope_0",
  "location": "westeurope",
  "name": "azure-toolbox--django-demo",
  "os": "Linux",
  "resourcegroup": "xx_xx_Linux_westeurope",
  "runtime_version": "python|3.7",
  "runtime_version_detected": "-",
  "sku": "FREE",
  "src_path": ".../Working-with_Django"
}

Additional Reading

Installation

Here is the documentation from Microsoft.

Mac OS

Install with Homebrew

$ brew update && brew install azure-cli
$ az login