Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.DS_Store
.settings/
# Compiled class file
*.class

Expand Down
114 changes: 114 additions & 0 deletions .mvn/wrapper/MavenWrapperDownloader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at

https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.Properties;

public class MavenWrapperDownloader {

/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL =
"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";

/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";

/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";

/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";

public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());

// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: : " + url);

File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}

private static void downloadFileFromURL(String urlString, File destination) throws Exception {
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}

}
1 change: 1 addition & 0 deletions .mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
129 changes: 78 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# YugaStore in Java

This is an implementation of a sample ecommerce app. This microservices-based retail marketplace or eCommerce app is composed of **microservices written in Spring (Java)**, a **UI based on React** and **YugaByte DB as the distributed SQL database**.
This is an implementation of a sample ecommerce app. This microservices-based retail marketplace or eCommerce app is composed of **microservices written in Spring (Java)**, a **UI based on React** and **YugaByte DB as the distributed SQL database**.

If you're using this demo app, please :star: this repository! We appreciate your support.

Expand All @@ -22,108 +22,135 @@ You can also [try the app out](https://yugastore-ui.cfapps.io/) online, it is ho

The architecture diagram of YugaStore is shown below.

![Architecture of microservices based retail marketplace app](yugastore-java-architecture.png)
![Architecture of microservices based retail marketplace app](yugastore-java-k8s-architecture.png)


| Microservice | YugaByte DB API | Default host:port | Description |
| -------------------- | ---------------- | ---------------- | --------------------- |
| [service discovery](https://github.com/YugaByte/yugastore-java/tree/master/eureka-server-local) | - | [localhost:8761](http://localhost:8761) | Uses **Eureka** for localhost. All microservices register with the Eureka service. This registration information is used to discover dynamic properties of any microservice. Examples of discovery include finding the hostnames or ip addresses, the load balancer and the port on which the microservice is currently running.
| [react-ui](https://github.com/YugaByte/yugastore-java/tree/master/react-ui) | - | [localhost:8080](http://localhost:8080) | A react-based UI for the eCommerce online marketplace app.
| [api-gateway](https://github.com/YugaByte/yugastore-java/tree/master/api-gateway-microservice) | - | [localhost:8081](http://localhost:8081) | This microservice handles all the external API requests. The UI only communicates with this microservice.
| [products](https://github.com/YugaByte/yugastore-java/tree/master/products-microservice) | YCQL | [localhost:8082](http://localhost:8082) | This microservice contains the entire product catalog. It can list products by categories, return the most popular products as measured by sales rank, etc.
| [cart](https://github.com/YugaByte/yugastore-java/tree/master/cart-microservice) | YCQL | [localhost:8083](http://localhost:8083) | This microservice deals with users adding items to the shopping cart. It has to be necessarily highly available, low latency and often multi-region.
| [checkout](https://github.com/YugaByte/yugastore-java/tree/master/checkout-microservice) | YSQL | [localhost:8086](http://localhost:8086) | This deals with the checkout process and the placed order. It also manages the inventory of all the products because it needs to ensure the product the user is about to order is still in stock.
| [login](https://github.com/YugaByte/yugastore-java/tree/master/login-microservice) | YSQL | [localhost:8085](http://localhost:8085) | Handles login and authentication of the users. *Note that this is still a work in progress.*
| Microservice | YugaByte DB API | Description |
| -------------------- | --------------- | --------------------- |
| [react-ui](https://github.com/YugaByte/yugastore-java/tree/master/react-ui) | - | A react-based UI for the eCommerce online marketplace app.
| [api-gateway](https://github.com/YugaByte/yugastore-java/tree/master/api-gateway-microservice) | - | This microservice handles all the external API requests. The UI only communicates with this microservice.
| [products](https://github.com/YugaByte/yugastore-java/tree/master/products-microservice) | YCQL | This microservice contains the entire product catalog. It can list products by categories, return the most popular products as measured by sales rank, etc.
| [cart](https://github.com/YugaByte/yugastore-java/tree/master/cart-microservice) | YCQL | This microservice deals with users adding items to the shopping cart. It has to be necessarily highly available, low latency and often multi-region.
| [checkout](https://github.com/YugaByte/yugastore-java/tree/master/checkout-microservice) | YSQL | This deals with the checkout process and the placed order. It also manages the inventory of all the products because it needs to ensure the product the user is about to order is still in stock.
| [login](https://github.com/YugaByte/yugastore-java/tree/master/login-microservice) | YSQL | Handles login and authentication of the users. *Note that this is still a work in progress.*

# Build and run

## Build Jars with Maven
To build, simply run the following from the base directory:

```
$ mvn -DskipTests package
```

To run the app, you need to first install YugaByte DB, create the necessary tables, start each of the microservices and finally the React UI.

## Running the app
## Build a Docker Image with Maven

Make sure you have built the app as described above. Now do the following steps.
To get started quickly, you can run Jib without even changing your pom.xml:

## Step 1: Install and initialize YugaByte DB

You can [install YugaByte DB by following these instructions](https://docs.yugabyte.com/latest/quick-start/).
```
$ ./mvnw com.google.cloud.tools:jib-maven-plugin:dockerBuild -Dimage=nchandrappa/cart-microservice
```

Now create the necessary tables as shown below. Note that these steps would take a few seconds.
To push to a Docker registry you use the build goal, instead of dockerBuild, i.e.

```
$ cd resources
$ cqlsh -f schema.cql
$ ./mvnw com.google.cloud.tools:jib-maven-plugin:build -Dimage=nchandrappa/cart-microservice
```
Next, load some sample data.

Note: Update docker image id to reflect the docker repository of your choice.


## Running the app on Minikube

To run the app on your local Minikube, you need to first install YugaByte DB, create the necessary tables, deploy microservices and the React UI.

Make sure you have built the docker images as described above and you're in the `yugastore-java` base directory. Now do the following steps.


## verify if minikube is running

```
$ cd resources
$ ./dataload.sh
$ minikube status
```

Create the postgres tables in `resources/schema.sql` for the YSQL tables.
## Step 1: Install and initialize YugaByte DB

## Step 2: Start the Eureka service discovery (local)
You can [install YugaByte DB by following these instructions](https://docs.yugabyte.com/latest/quick-start/).

You can do this as follows:
a. Install YugabyteDB in minikube

```
$ cd eureka-server-local/
$ mvn spring-boot:run
$ kubectl create -f k8s-deployments/util/default-rbac.yml
$ kubectl create namespace yb-demo
$ kubectl create -f k8s-deployments/Yugabyte/yugabyte-statefulset-rf-1.yaml -n yb-demo

```

Verify this is running by browsing to the [Spring Eureka Service Discovery dashboard](http://localhost:8761/).
b. Verify YugabyteDB installation by connecting to postgres terminal using the following command

## Step 2: Start the api gateway microservice
```
$ kubectl -n yb-demo exec -it yb-tserver-0 /home/yugabyte/bin/ysqlsh -- -h yb-tserver-0 --echo-queries
```

To run the products microservice, do the following in a separate shell:
c. find the YCQL and YSQL ip-address:port for YugabyteDB cluster by running the below command

```
$ cd api-gateway-microservice/
$ mvn spring-boot:run
$ minikube service yb-db-service -n yb-demo
```

set the following environment variables from above data. example:

## Step 3: Start the products microservice
```
$ export CQLSH_HOST=192.168.64.3
$ export CQLSH_PORT=31620
$ export YSQLSH_HOST=192.168.64.3
$ export YSQLSH_PORT=32517
```

To run the products microservice, do the following in a separate shell:
d. Now create the necessary tables as shown below. Load sample dataset by following the steps [here](resources/README.md)

```
$ cd products-microservice/
$ mvn spring-boot:run
$ cd resources
$ cqlsh -f schema.cql
```

## Step 4: Start the checkout microservice

To run the products microservice, do the following in a separate shell:
Next, load some sample data. Follow the data load steps in

```
$ cd checkout-microservice/
$ mvn spring-boot:run
$ cd resources
$ ./dataload.sh
```

## Step 5: Start the checkout microservice
Create the postgres tables in `resources/schema.sql` for the YSQL tables

To run the cart microservice, do the following in a separate shell:
```
$ ysqlsh -h $YSQLSH_HOST -p $YSQLSH_PORT -d postgres -f schema.sql
```

## Step 2: Deploy yugastore-java microservices

```
$ cd cart-microservice/
$ mvn spring-boot:run
$ kubectl create -f k8s-deployments/microservices/yugastore-deployment.yaml
```

## Step 6: Start the UI

To do this, simply run `npm start` from the `frontend` directory in a separate shell:
## Step 3: browse to the marketplace app

```
$ cd react-ui
$ mvn spring-boot:run
$ minikube service yugastore-ui
```

Now browse to the marketplace app at [http://localhost:8080/](http://localhost:8080/).
this command will open up Yugastore Dashboard.


# Next Steps

- [Deploy Yugastore on Istio enabled Kubernetes Cluster](k8s-deployoment-instructions.md)


# Learn more

- [Learn YugabyteDB](https://learn.yugabyte.com/)
- [Contribute to YugabyteDB](https://www.yugabyte.com/community/)
- [Contribute to Spring Data YugabyteDB](https://github.com/yugabyte/spring-data-yugabytedb)
Loading