Create Spring Boot Project
On the Eclipse, create a Spring Boot project
Enter Project Information:
- Name: WebAPIServer
- Group: com.demo
- Artifact: WebAPIServer
- Description: Web API Server
- Package: com.demo
Select the technologies and libraries to be used:
- JPA
- MySQL
- Web
Click Next button to show Site Information for project
Click Finish button to finish create Spring Boot project
Configure pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>WebAPIServer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>WebAPIServer</name>
<description>Web API Server</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Create Database
Create a database with the name is web_api_server. This database have 1 table: Product table
--
-- Table structure for table `product`
--
CREATE TABLE `product` (
`id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` varchar(250) NOT NULL,
`price` double NOT NULL,
`quantity` int(11) NOT NULL,
`description` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
--
-- Dumping data for table `product`
--
INSERT INTO `product` (`id`, `name`, `price`, `quantity`, `description`) VALUES
(1, 'Computer 1', 14, 2, 'Description 1'),
(2, 'Computer 2', 5, 7, 'Description 2'),
(3, 'Mobile 1', 7, 4, 'Description 3'),
(4, 'Mobile 2', 11, 8, 'Description 4'),
(5, 'Mobile 3', 7, 9, 'Description 5');
Structure of Product Table
Data of Product Table
Configure application.properties
spring.datasource.url= jdbc:mysql://localhost:3306/web_api_server
spring.datasource.username=root
spring.datasource.password=123456
server.port=9596
Entities Class
Create new package named com.demo.entities. In this package, create a entity class – Product.java, to represent the above table
Product Entity
package com.demo.entities;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "product")
public class Product implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private double price;
private int quantity;
private String description;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Create ProductRepository Interface
Create new package named com.demo.repositories. In this package create the ProductRepository interface implements from CrudRepository interface of Spring Data JPA that provides CRUD operations for an entity.
package com.demo.repositories;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import com.demo.entities.Product;
@Repository("productRepository")
public interface ProductRepository extends CrudRepository<Product, Integer> {
}
Create ProductService Interface
The ProductService.java interface contains methods to interact with the database.
package com.demo.services;
import com.demo.entities.Product;
public interface ProductService {
public Iterable<Product> findAll();
}
Create ProductServiceImpl class
The ProductServiceImpl.java class implements methods from ProductService.java interfaces that contains methods to interact with the database.
package com.demo.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.demo.entities.Product;
import com.demo.repositories.ProductRepository;
@Service("productService")
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductRepository productRepository;
@Override
public Iterable<Product> findAll() {
return productRepository.findAll();
}
}
Create Rest API Controller
Create new package named com.demo.controllers. In this package, create controller as below:
ProductController
Create new java class, named ProductController.java
package com.demo.controllers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MimeTypeUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.demo.entities.Product;
import com.demo.services.ProductService;
@RestController
@RequestMapping("api/product")
public class ProductController {
@Autowired
private ProductService productService;
@RequestMapping(value = "findall",
method = RequestMethod.GET,
produces = { MimeTypeUtils.APPLICATION_JSON_VALUE },
headers = "Accept=application/json")
public ResponseEntity<Iterable<Product>> findAll() {
try {
Iterable<Product> products = productService.findAll();
return new ResponseEntity<Iterable<Product>>(products, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<Iterable<Product>>(HttpStatus.BAD_REQUEST);
}
}
}
Testing Web API Controller
Access Rest API Controller use the following url: http://localhost:9596/api/product/findall
Output
[
{"id":"1","name":"Computer 1","price":14.0,"quantity":2,"description":"Description 1"},
{"id":"2","name":"Computer 2","price":5.0,"quantity":7,"description":"Description 2"},
{"id":"3","name":"Mobile 1","price":7.0,"quantity":4,"description":"Description 3"},
{"id":"4","name":"Mobile 2","price":11.0,"quantity":8,"description":"Description 4"},
{"id":"5","name":"Mobile 3","price":7.0,"quantity":9,"description":"Description 5"}
]
Structure of Spring Boot Project
Create Android Project
Create new project in Android Studio with steps as below:
Step 1: Input Project Name and Select Project Location
Step 2: Select SDK for Android App
Step 3: Select Default Activity for App
Step 4: Finish create project
Add Strings
Open res\values\strings.xml file and add new string as below:
<resources>
<string name="app_name">Learn Android with Real Apps</string>
<string name="usd">$</string>
</resources>
Add Library as Dependencies
Open build.gradle file in Gradle Scripts and add Retrofit libraies as below:
implementation 'com.squareup.retrofit2:retrofit:2.3.0'
implementation 'com.google.code.gson:gson:2.6.2'
implementation 'com.squareup.retrofit2:converter-gson:2.1.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.4.1'
implementation 'com.squareup.okhttp3:okhttp:3.4.1'
Manifest Permissions
Open AndroidManifest.xml file in manifest folder, add permissions as below:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.demo.learnandroidwithrealapps">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Create Entities
Create new package named entities. In this package, create new java class named Product.java as below:
package android.demo.entities;
import com.google.gson.annotations.SerializedName;
import java.io.Serializable;
public class Product implements Serializable {
@SerializedName("id")
private int id;
@SerializedName("name")
private String name;
@SerializedName("price")
private double price;
@SerializedName("quantity")
private int quantity;
@SerializedName("description")
private String description;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
}
Create Custom ListView Layout
Select res\layout folder. In this folder, create new layout named product_row_layout.xml as below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textViewName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="bold" />
<TextView
android:id="@+id/textViewDescription"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/textViewPrice"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Create Custom Adapter
Create new package named adapters. In this package, create new java class named ProductListAdapter.java as below:
package android.demo.adapters;
import android.content.Context;
import android.demo.entities.Product;
import android.demo.learnandroidwithrealapps.R;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
public class ProductListAdapter extends ArrayAdapter<Product> {
private List<Product> products;
private Context context;
public ProductListAdapter(List<Product> products, Context context) {
super(context, R.layout.product_row_layout, products);
this.context = context;
this.products = products;
}
@NonNull
@Override
public View getView(int position, @Nullable View view, @NonNull ViewGroup parent) {
ViewHolder viewHolder;
if (view == null) {
viewHolder = new ViewHolder();
LayoutInflater layoutInflater = LayoutInflater.from(context);
view = layoutInflater.inflate(R.layout.product_row_layout, parent, false);
viewHolder.textViewName = view.findViewById(R.id.textViewName);
viewHolder.textViewPrice = view.findViewById(R.id.textViewPrice);
viewHolder.textViewDescription = view.findViewById(R.id.textViewDescription);
} else {
viewHolder = (ViewHolder) view.getTag();
}
Product product = products.get(position);
viewHolder.textViewName.setText(product.getName());
viewHolder.textViewDescription.setText(product.getDescription());
viewHolder.textViewPrice.setText(context.getText(R.string.usd) + String.valueOf(product.getPrice()));
return view;
}
private static class ViewHolder {
public static TextView textViewName;
public static TextView textViewDescription;
public static TextView textViewPrice;
}
}
Retrofit API
Create new package named api. In this package, create new api as below:
APIClient
Create new java class named APIClient.java as below:
package android.demo.services;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class APIClient {
private static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
retrofit = new Retrofit.Builder()
.baseUrl("http://192.168.0.102:9596/api/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
Product API
Create new interface named ProductAPI.java as below:
package android.demo.services;
import android.demo.entities.Product;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
public interface ProductAPI {
@GET("product/findall")
Call<List<Product>> findAll();
}
Main Activity Layout
Open res\layout\activity_main.xml file and create layout as below:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:orientation="vertical"
tools:ignore="HardcodedText">
<ListView
android:id="@+id/listViewProduct"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Main Activity Class
Add code to MainActivity.java in android.demo.learnandroidwithrealapps package as below:
package android.demo.learnandroidwithrealapps;
import android.demo.adapters.ProductListAdapter;
import android.demo.entities.Product;
import android.demo.services.APIClient;
import android.demo.services.ProductAPI;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import android.widget.Toast;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private ListView listViewProduct;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
loadData();
}
private void initView() {
listViewProduct = findViewById(R.id.listViewProduct);
}
private void loadData() {
ProductAPI productAPI = APIClient.getClient().create(ProductAPI.class);
productAPI.findAll().enqueue(new Callback<List<Product>>() {
@Override
public void onResponse(Call<List<Product>> call, Response<List<Product>> response) {
try {
if (response.isSuccessful()) {
List<Product> products = response.body();
listViewProduct.setAdapter(new ProductListAdapter(products, getApplicationContext()));
} else {
Toast.makeText(getApplicationContext(), response.errorBody().string(), Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
@Override
public void onFailure(Call<List<Product>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
Structure of Project
Run App
Load Main Activity