How to Install Nginx as a reverse proxy server

Let’s assumeyou have Nginx installed, here are the steps to set up reverse proxy server:

1. create a config file under /etc/nginx/sites-available/leespace.com
2. Change the configure by editing example.com to have the following:

server {
    listen 80;

    server_name leespace.com www.leespace.com;

    location /blog {

        proxy_pass http://localhost:88/blog;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

    }
}

3. Create a symbolic link :
sudo ln -s /etc/nginx/sites-available/leesapce.com /etc/nginx/sites-enabled/leesapce.com

4. Restart nginx server with : service nginx restart

5. Optional step : set up your land page at /usr/share/nginx/html

Read More

Git cherry-pick from another repository

Git cherry-pick from another repository


# Cloning our fork
$ git clone git clone git@gitlab.com:tongancity/Leespace-git-demo.git

# Adding (as "demo2") the repo from we want to cherry-pick
$ git remote add demo2 git@gitlab.com:tongancity/Leespace-git-demo2.git

# Fetch their branches
$ git fetch demo2

# List their commits
$ git log  demo2/develop 

# Cherry-pick the commit we need
$ git cherry-pick  d434sgdffedac 

# Pushing to our master
$ git push origin develope

Read More

NgInx with Docker

You need to pull docker image for nginx first with : docker pull nginx, the following command will run nginx on docker container by exposing port 80 to the public.

sudo docker run –name docker-nginx -p 80:80 -e TERM=xterm -d nginx

go to docker local:
docker exec -it CONTAINER_ID bash

Read More

Docker deployment for Spring boot application

Docker deployment of spring boot application is a hot topic in the recent years, here are the detailed steps:Create a spring boot application: start with https://start.spring.io/, select Reactive web and Reactive Mongodb and provide group and artifact, generate project.

Import the generated project into STS (or eclipse)

Spring boot application

package com.leespace.bookstore;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;

import com.mongodb.ConnectionString;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;

@SpringBootApplication(exclude = { MongoAutoConfiguration.class, MongoDataAutoConfiguration.class })
@EnableReactiveMongoRepositories
@AutoConfigureAfter(EmbeddedMongoAutoConfiguration.class)
public class BookstoreMongoSpringBootApplication extends AbstractReactiveMongoConfiguration {

	
    private final Environment environment;
	 
    public BookstoreMongoSpringBootApplication(Environment environment) {
        this.environment = environment;
    }
	public static void main(String[] args) {
		SpringApplication.run(BookstoreMongoSpringBootApplication.class, args);
	}

	@Override
	public MongoClient reactiveMongoClient() {
		MongoClient mongoClient = MongoClients.create(new ConnectionString(environment.getProperty("spring.data.mongodb.uri")));
		return mongoClient;
	}

	@Override
	protected String getDatabaseName() {
		return "leespacedb";
	}
}

Create Entity class

package com.leespace.bookstore.entity;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import lombok.Data;
import lombok.RequiredArgsConstructor;

@Data
@Document
@RequiredArgsConstructor
public class Product {
	@Id
	private int id;
	private String name;
	private String description;
	private String author;
	private String category;
	private double price;
	private String imageUrl;
	
	public Product(int id, String name, String description, String author, String category, double price,
			String imageUrl) {
		super();
		this.id = id;
		this.name = name;
		this.description = description;
		this.author = author;
		this.category = category;
		this.price = price;
		this.imageUrl = imageUrl;
	}
	
	
}

Create ReactiveRepository

package com.leespace.bookstore.repository;

import org.springframework.data.mongodb.repository.Query;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
import org.springframework.stereotype.Component;

import com.leespace.bookstore.entity.Product;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Component
public interface ReactiveProductRepository extends ReactiveCrudRepository<Product, String> {
    Flux<Product> findByName(String name);

    Flux<Product> findByName(Mono<String> name);

    Mono<Product> findByNameAndImageUrl(Mono<String> name, String imageUrl);

    @Query("{ 'name': ?0, 'imageUrl': ?1}")
    Mono<Product> findByNameAndImageUrl(String name, String imageUrl);
}

Create RestController

package com.leespace.bookstore.rest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.leespace.bookstore.entity.Product;
import com.leespace.bookstore.repository.ReactiveProductRepository;

import reactor.core.publisher.Flux;

@RestController
public class ProductController {

	@Autowired
	private ReactiveProductRepository propductRepository;

	@GetMapping("/products")
	public Flux<Product> getAllProducts() {
		return propductRepository.findAll();
	}

}

Create Dockerfile

FROM frolvlad/alpine-oraclejdk8:slim
EXPOSE 8080
RUN mkdir -p /app/
ADD target/bookstore-mongo-spring-boot-0.0.1-SNAPSHOT.jar /app/bookstore-mongo-spring-boot.jar
ENTRYPOINT ["java", "-jar", "/app/bookstore-mongo-spring-boot.jar"]

Build docker image

docker build . -t bookstore-mongo-spring-boot

Run spring boot app in a docker container.

Firstly clean up stopped containers: 
docker rm $(docker ps -a -q)
docker run --name="bookstore-mongo-spring-boot-A" --restart unless-stopped --publish 9001:8080 --detach bookstore-mongo-spring-boot 

docker run --name="bookstore-mongo-spring-boot-B" --restart unless-stopped --publish 9002:8080 --detach bookstore-mongo-spring-boot 

You can insert some records in the product collection with the following:

db.product.insert({ “_id” : 1,”name”:”Java”, “description” : “Java introduction”, “author” : “Jack”, “category” : “Book”, “price” : 234, “imageUrl” : “javaUrl”, “_class” : “com.leespace.bookstore.entity.Product”} );

db.product.insert({ “_id” : 2, “name” : “Nodejs”, “description” : “Nodejs introduction”, “author” : “John”, “category” : “Book”, “price” : 134, “imageUrl” : “Nodejsurl” ,”_class” : “com.leespace.bookstore.entity.Product”})

You can check http://localhost:9001/products or http://localhost:9002/products
The expected rest response will be like :

{
"id": 1,
"name": "Java",
"description": "Java introduction",
"author": "Jack",
"category": "Book",
"price": 234,
"imageUrl": "javaUrl"
},
{
"id": 2,
"name": "Nodejs",
"description": "Nodejs introduction",
"author": "steve",
"category": "Book",
"price": 134,
"imageUrl": "Nodejsurl"
}

Read More

java.util.concurrent CountDownLatch explained.


import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ThreadRunner implements Runnable {
    private List<  String> eventList;
    private CountDownLatch countDownLatch;
 
    public ThreadRunner(List<  String> outputScraper, CountDownLatch countDownLatch) {
        this.eventList = outputScraper;
        this.countDownLatch = countDownLatch;
    }
 
    @Override
    public void run() {
        doSomeWork();
        eventList.add("event " + countDownLatch.getCount());
        countDownLatch.countDown();
    }

	private void doSomeWork() {
		System.out.println("do something..."   + countDownLatch.getCount());
	}
}

package com.leespace.training.thread;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

public class ThreadRunnerTest {
	@Test
	public void whenParallelProcessing_thenMainThreadWillBlockUntilCompletion() throws InterruptedException {
        int counter = 6;
		List<String> events = Collections.synchronizedList(new ArrayList<>());
		CountDownLatch countDownLatch = new CountDownLatch(counter);
		List<Thread> workers = Stream.generate(() -> new Thread(new ThreadRunner(events, countDownLatch))).limit(counter)
				.collect(Collectors.toList());

		workers.forEach(Thread::start);
		countDownLatch.await();
		events.add("This ia the last event");

		events.forEach(a -> System.out.println(a));

	}
}

Output:

do something…6
do something…6
do something…4
do something…3
do something…2
do something…1
event 6
event 5
event 4
event 3
event 2
event 1
This ia the last event

Read More

Javascript: Processing collections with map, reduce, and filter

Map executes that callback on every element within it, returning a new array with all of the values that the callback returned. Map passes three arguments to your callback:

  • The current item in the array
  • The current index
  • The entire array you called map on

Filter takes an array, and filters out unwanted elements.Filter passes your callback three arguments:

  • The current item
  • The current index
  • The array you called filter on

Reduce takes all of the elements in an array, and reduces them into a single value. Reduce passes your callback four arguments:

  • The current value
  • The previous value
  • The current index
  • The array you called reduce on
  •  
     	 
    var isEven = num => num % 2 === 0;
    var square = num => num * num;
    var add = (a, b) => a + b;
      
    var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      
    arr.filter(isEven).map(square).reduce(add); 
    
    
    Output: 220
    

Read More