{{announcement.body}}
{{announcement.title}}

iOS Spring Boot Code Generation in One Minute With Clowiz

DZone 's Guide to

iOS Spring Boot Code Generation in One Minute With Clowiz

To increase software developers' productivity and to reduce the cost of software development, the Clowiz platform has been created.

· Web Dev Zone ·
Free Resource

With the current trends in the software development field, agility and faster delivery of software applications have become an essential part of the IT industry. In fact, this has been one of the main reasons for the evolution of many of the modern technologies and trends, such as single-page applications, lightweight frameworks, and microservices architecture.

Even with the massive improvements in the technologies, IDEs, and tools, developers still write much code to get the job done. To increase software developers' productivity and to reduce the cost of software development, the Clowiz platform has been created.

Clowiz is a cloud-based platform that enables developers to generate software artifacts (using CodeGen), end-to-end features (using FeatureGen), and full end-to-end apps (using AppGen) without writing a single line of code. 

In this article, we are going to:

  1. Create and set up the following projects:
    • iOS Swift App
    • Spring Boot Rest API
  2. Generate app artifacts using Clowiz:
    • Generate and use the following artifacts in the iOS App:
      • List ViewController
      • Add/Edit ViewController
      • List View
      • Add/Edit View
      • Model 
      • Alamofire Sevice
    • Generate and use the following artifacts in the Spring Boot App:
      • JPA Repository
      • Entity
      • Rest API Controller
  3. Run and test the project

Create iOS Swift App

Using XCode:

  • Create a new iOS Storyboard project with a Single View App.
  • Add Alamofire POD to the project. (How to add Alamofire to xCode,  Alamofire latest version)
  • Delete the "Main.storyboard" file and its references from the "Info.plist" file. (Create project without storyboard)
  • Rename the file "ViewController.swift" to "TabBarVC.swift". 
  • Change the class name to TabBarVC.
  • Change the rootViewCntroller to a to our TabBarVC by replacing the scene function in the SceneDelegate.swift file with the following:
Swift
 







  • Create a new subclass of UIViewController and call it "HomeVC.swift" with the following content:
Swift
 







  • Add UINavigationController to your tabs in the TabBarVC class.
Swift
 







Running the app displays the TabBar and an empty Home navigation page, now we can extend the app and add more functionalities to it.

Generate iOS Artifacts

To boost the development process, use the CodeGen feature from Clowiz to generate the project artifacts source code in one minute for both applications.

Clowiz CodeGen

To generate the artifacts for both applications, iOS, and Spring Boot:
  1. Go to Clowiz, then navigate to CodeGen https://www.clowiz.com/
  2. From the technologies, choose iOS.
  3. In the metadata section, name your artifacts, e.g., Employee.
  4. For the first field, in the field name, type Name and keep is as Text.
  5. Create two more fields, e.g., Email and Salary, with data types of email and double.
  6. Check all fields as required. 

CodeGen has generated the following artifacts for the project:

Model.

Swift
 




xxxxxxxxxx
1
14


1
import UIKit
2
 
          
3
class Employee: NSObject, Codable {
4
    
5
    var id: Int?
6
    var name: String?
7
    var email: String?
8
    var salary: Double?
9
    
10
    override init() {
11
        super.init()
12
    }
13
    
14
}



Cell View: represents the data in each table row: 

Swift
 




x


 
1
import UIKit
2
 
          
3
class EmployeeCell: UITableViewCell {
4
    
5
    var idLabel = UILabel()
6
    var id = UILabel()
7
    var nameLabel = UILabel()
8
    var name = UILabel()
9
    var emailLabel = UILabel()
10
    var email = UILabel()
11
    var salaryLabel = UILabel()
12
    var salary = UILabel()
13
    
14
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
15
        super.init(style: style, reuseIdentifier: reuseIdentifier)
16
        addSubViews()
17
    }
18
    
19
    required init?(coder: NSCoder) {
20
        super.init(coder: coder)
21
    }
22
    
23
    func addSubViews() {
24
        idLabel.text = "Id:"
25
        self.addSubview(idLabel)
26
        self.addSubview(id)
27
        nameLabel.text = "Name:"
28
        self.addSubview(nameLabel)
29
        self.addSubview(name)
30
        emailLabel.text = "Email:"
31
        self.addSubview(emailLabel)
32
        self.addSubview(email)
33
        salaryLabel.text = "Salary:"
34
        self.addSubview(salaryLabel)
35
        self.addSubview(salary)
36
        
37
        setupFields()
38
    }
39
    
40
    func setupFields() {
41
        id.anchor(top: self.topAnchor, bottom: nil, left: idLabel.rightAnchor, right: nil)
42
        idLabel.anchor(top: self.topAnchor, bottom: nil, left: self.leftAnchor, right: nil)
43
        name.anchor(top: id.bottomAnchor, bottom: nil, left: nameLabel.rightAnchor, right: nil)
44
        nameLabel.anchor(top: idLabel.bottomAnchor, bottom: nil, left: self.leftAnchor, right: nil)
45
        email.anchor(top: name.bottomAnchor, bottom: nil, left: emailLabel.rightAnchor, right: nil)
46
        emailLabel.anchor(top: nameLabel.bottomAnchor, bottom: nil, left: self.leftAnchor, right: nil)
47
        salary.anchor(top: email.bottomAnchor, bottom: self.bottomAnchor, left: salaryLabel.rightAnchor, right: nil)
48
        salaryLabel.anchor(top: emailLabel.bottomAnchor, bottom: self.bottomAnchor, left: self.leftAnchor, right: nil)
49
    }
50
    
51
    func setEmployee(employee: Employee) {
52
        id.text = String(employee.id ?? 0)
53
        name.text = (employee.name?.elementsEqual(""))! ? "-" : employee.name
54
        email.text = (employee.email?.elementsEqual(""))! ? "-" : employee.email
55
        salary.text = String(employee.salary ?? 0.0)
56
    }
57
}


 

Add Edit View: holds the input fields(name, email, salary input fields) and their labels.

Swift
 




x


1
import UIKit
2
 
          
3
class AddEmployeeView: UIView, UITextFieldDelegate {
4
    
5
    var nameLabel = UILabel()
6
    var name = UITextField()
7
    var emailLabel = UILabel()
8
    var email = UITextField()
9
    var salaryLabel = UILabel()
10
    var salary = UITextField()
11
    
12
    var scrollView = UIScrollView()
13
    
14
    var textFields: [UITextField] {
15
        return [name,email,salary]
16
    }
17
    
18
    override init(frame: CGRect) {
19
        super.init(frame: frame)
20
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
21
        self.addGestureRecognizer(tap)
22
        setupScrollView()
23
        setupFields()
24
    }
25
    
26
    required init?(coder: NSCoder) {
27
        super.init(coder: coder)
28
    }
29
    
30
    func setupFields() {
31
        textFields.forEach { $0.delegate = self }
32
        nameLabel.text = "Name: *"
33
        name.placeholder = "Name"
34
        emailLabel.text = "Email: *"
35
        email.keyboardType = .emailAddress
36
        email.placeholder = "Email"
37
        salaryLabel.text = "Salary: *"
38
        salary.keyboardType = .decimalPad
39
        salary.placeholder = "Salary"
40
        
41
        setFieldConstraints()
42
    }
43
    
44
    func setFieldConstraints() {
45
        nameLabel.anchor(top: scrollView.topAnchor, bottom: nil, left: scrollView.leftAnchor, right: nil)
46
        name.anchor(top: scrollView.topAnchor, bottom: nil, left: nameLabel.rightAnchor, right: nil)
47
        emailLabel.anchor(top: nameLabel.bottomAnchor, bottom: nil, left: scrollView.leftAnchor, right: nil)
48
        email.anchor(top: name.bottomAnchor, bottom: nil, left: emailLabel.rightAnchor, right: nil)
49
        salaryLabel.anchor(top: emailLabel.bottomAnchor, bottom: scrollView.bottomAnchor, left: scrollView.leftAnchor, right: nil)
50
        salary.anchor(top: email.bottomAnchor, bottom: scrollView.bottomAnchor, left: salaryLabel.rightAnchor, right: nil)
51
    }
52
    
53
    func setupScrollView() {
54
        self.addSubview(scrollView)
55
        scrollView.addSubview(nameLabel)
56
        scrollView.addSubview(name)
57
        scrollView.addSubview(emailLabel)
58
        scrollView.addSubview(email)
59
        scrollView.addSubview(salaryLabel)
60
        scrollView.addSubview(salary)
61
        scrollView.contentSize.height = 2000
62
        scrollView.anchor(top: self.topAnchor, bottom: self.bottomAnchor, left: self.leftAnchor, right: self.rightAnchor)
63
    }
64
    
65
    @objc func dismissKeyboard() {
66
        self.endEditing(true)
67
    }
68
    
69
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
70
        if let selectedTextFieldIndex = textFields.firstIndex(of: textField), selectedTextFieldIndex < textFields.count - 1 {
71
            textFields[selectedTextFieldIndex + 1].becomeFirstResponder()
72
        } else {
73
            textField.resignFirstResponder()
74
        }
75
        return true
76
    }
77
    
78
}
79
 
          
80
extension UIView {
81
    func anchor(top: NSLayoutYAxisAnchor?, bottom: NSLayoutYAxisAnchor?, left: NSLayoutXAxisAnchor?, right: NSLayoutXAxisAnchor?) {
82
        translatesAutoresizingMaskIntoConstraints = false
83
        if let top = top {
84
            topAnchor.constraint(equalTo: top, constant: 15).isActive = true
85
        }
86
        if let left = left {
87
            leftAnchor.constraint(equalTo: left, constant: 15).isActive = true
88
        }
89
        if let right = right {
90
            rightAnchor.constraint(equalTo: right, constant: -15).isActive = true
91
        }
92
        if let bottom = bottom {
93
            bottomAnchor.constraint(equalTo: bottom, constant: -15).isActive = true
94
        }
95
    }
96
}



Add Edit VC: used to add and edit data.

Swift
 




x


 
1
import UIKit
2
 
          
3
class AddEmployeeVC: UIViewController {
4
    
5
    var addEmployeeView = AddEmployeeView()
6
    var employeeService = EmployeeService()
7
    var employee = Employee()
8
    
9
    override func loadView() {
10
        view = addEmployeeView
11
    }
12
    
13
    override func viewDidLoad() {
14
        super.viewDidLoad()
15
        view.backgroundColor = .white
16
        isEditMode()
17
    }
18
    
19
    func isEditMode() {
20
        if(employee.id != nil) {
21
            addEmployeeView.name.text = employee.name
22
            addEmployeeView.email.text = employee.email
23
            addEmployeeView.salary.text = String(employee.salary ?? 0.0)
24
            navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(updateEmployee))
25
        } else {
26
            navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(createEmployee))
27
        }
28
    }
29
    
30
    @objc func createEmployee() {
31
        if(validate()) {
32
            employeeService.createEmployee(employee: employee){ (res) in
33
                switch res {
34
                case .success(_):
35
                    NotificationCenter.default.post(name: Notification.Name("reloadNotification"), object: nil)
36
                    self.navigationController?.popViewController(animated: true)
37
                case .failure(_):
38
                    self.showAlert(withTitle: "Network Error",
39
                        withMessage: "Failed to create Employee",
40
                        parentController: self,
41
                        okBlock: {},
42
                        cancelBlock: nil)
43
                }
44
            }
45
        }
46
    }
47
    
48
    @objc func updateEmployee() {
49
        if(validate()) {
50
            employeeService.updateEmployee(id: employee.id!, employee: employee){ (res) in
51
                switch res {
52
                case .success(_):
53
                    NotificationCenter.default.post(name: Notification.Name("reloadNotification"), object: nil)
54
                    self.navigationController?.popViewController(animated: true)
55
                case .failure(_):
56
                    self.showAlert(withTitle: "Network Error",
57
                        withMessage: "Failed to update Employee",
58
                        parentController: self,
59
                        okBlock: {},
60
                        cancelBlock: nil)
61
                }
62
            }
63
        }
64
    }
65
    
66
    func validate() -> Bool {
67
        if(addEmployeeView.name.text!.isEmpty) {
68
            showAlert(withTitle: "Failed to add Employee",
69
                withMessage: "Name is required.",
70
                parentController: self,
71
                okBlock: {},
72
                cancelBlock: nil)
73
            return false
74
        }
75
        employee.name = addEmployeeView.name.text
76
        if(addEmployeeView.email.text!.isEmpty) {
77
            showAlert(withTitle: "Failed to add Employee",
78
                withMessage: "Email is required.",
79
                parentController: self,
80
                okBlock: {},
81
                cancelBlock: nil)
82
            return false
83
        }
84
        employee.email = addEmployeeView.email.text
85
        if(addEmployeeView.salary.text!.isEmpty) {
86
            showAlert(withTitle: "Failed to add Employee",
87
                withMessage: "Salary is required.",
88
                parentController: self,
89
                okBlock: {},
90
                cancelBlock: nil)
91
            return false
92
        }
93
        employee.salary = Double(addEmployeeView.salary.text ?? "0.0")
94
        return true
95
    }
96
    
97
}
98
extension UIViewController {
99
    func showAlert(withTitle title : String, withMessage message: String?, parentController parent : UIViewController, okBlock : @escaping () -> (), cancelBlock : (() -> ())?) {
100
        let alert : UIAlertController = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
101
        let okAction : UIAlertAction = UIAlertAction(title: "OK", style: UIAlertAction.Style.default) { (alert : UIAlertAction) in
102
            okBlock()
103
        }
104
        if (cancelBlock != nil) {
105
            let cancelAction : UIAlertAction = UIAlertAction(title: "Cancel", style: UIAlertAction.Style.default) { (alert : UIAlertAction) in
106
                cancelBlock!()
107
            }
108
            alert.addAction(cancelAction)
109
        }
110
        alert.addAction(okAction)
111
        parent.present(alert, animated: true) {
112
        }
113
    }
114
}



List VC: used to list and delete data. 

Swift  




x


 
1
import UIKit
2
 
          
3
class EmployeeListVC: UIViewController {
4
    
5
    var employeeTable = UITableView()
6
    var employeeService = EmployeeService()
7
    var employees: [Employee] = []
8
    
9
    var searchBar = UISearchBar()
10
    var isSearching: Bool = false
11
    var searchResults: [Employee] = []
12
    let refreshControl = UIRefreshControl()
13
    
14
    override func viewDidLoad() {
15
        super.viewDidLoad()
16
        navigationItem.title = "Employee"
17
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add", style: .plain, target: self, action: #selector(create))
18
        NotificationCenter.default.addObserver(self, selector: #selector(reload), name: Notification.Name("reloadNotification"), object: nil)
19
        self.setupSearchBar()
20
        self.setupEmployeeTable()
21
        self.getAllEmployees()
22
    }
23
    
24
    @objc func refresh(sender: UIRefreshControl){
25
        self.getAllEmployees()
26
        sender.endRefreshing()
27
    }
28
    
29
    @objc func reload(notification: NSNotification){
30
        self.getAllEmployees()
31
    }
32
    
33
    @objc func create() {
34
        let addEmployeeVC = AddEmployeeVC()
35
        addEmployeeVC.title = "Add Employee"
36
        self.navigationController?.pushViewController(addEmployeeVC, animated: true)
37
    }
38
    
39
    func getAllEmployees() {
40
        employeeService.getAllEmployees() { (res) in
41
            switch res {
42
            case .success(let employees):
43
                self.employees = employees
44
                self.employeeTable.reloadData()
45
            case .failure(_):
46
                self.showAlert(withTitle: "Network Error",
47
                    withMessage: "Failed to get Employee:",
48
                    parentController: self,
49
                    okBlock: {},
50
                    cancelBlock: nil)
51
            }
52
        }
53
    }
54
    
55
    func deleteEmployee(id: Int) {
56
        employeeService.deleteEmployee(id: id) { (res) in
57
            switch res {
58
            case .success(_):
59
                self.getAllEmployees()
60
            case .failure(_):
61
                self.showAlert(withTitle: "Network Error",
62
                    withMessage: "Failed to delete Employee:",
63
                    parentController: self,
64
                    okBlock: {},
65
                    cancelBlock: nil)
66
            }
67
        }
68
    }
69
    
70
    func setupSearchBar() {
71
        view.addSubview(searchBar)
72
        searchBar.delegate = self
73
        searchBar.anchor(top: view.safeAreaLayoutGuide.topAnchor, bottom: nil, left: view.leftAnchor, right: view.rightAnchor)
74
        searchBar.placeholder = " Search..."
75
        searchBar.delegate = self
76
    }
77
    
78
    func setupEmployeeTable() {
79
        view.addSubview(employeeTable)
80
        setEmployeeTableDelegates()
81
        employeeTable.frame = self.view.frame
82
        employeeTable.rowHeight = UITableView.automaticDimension
83
        employeeTable.register(EmployeeCell.self, forCellReuseIdentifier: "EmployeeCell")
84
        employeeTable.refreshControl = refreshControl
85
        refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged)
86
        employeeTable.anchor(top: searchBar.bottomAnchor, bottom: view.bottomAnchor, left: view.leftAnchor, right: view.rightAnchor)
87
    }
88
    
89
    func setEmployeeTableDelegates() {
90
        employeeTable.delegate = self
91
        employeeTable.dataSource = self
92
    }
93
    
94
    func dismissKeyboard() {
95
        self.view.endEditing(true)
96
    }
97
}
98
 
          
99
extension EmployeeListVC: UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
100
    
101
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
102
        if(isSearching){
103
            return searchResults.count
104
        }
105
        return employees.count
106
    }
107
    
108
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
109
        let cell = employeeTable.dequeueReusableCell(withIdentifier: "EmployeeCell") as! EmployeeCell
110
        let employee = employees[indexPath.row]
111
        if(isSearching){
112
            cell.setEmployee(employee: searchResults[indexPath.row])
113
        } else {
114
            cell.setEmployee(employee: employee)
115
        }
116
        return cell
117
    }
118
    
119
    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
120
        let delete = UIContextualAction(style: .destructive, title: "Delete", handler: { (action, view, success) in
121
            let employeeId = self.employees[indexPath.row].id
122
            self.deleteEmployee(id: employeeId ?? 0)
123
        })
124
        return UISwipeActionsConfiguration(actions: [delete])
125
    }
126
    
127
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
128
        let addEmployeeVC = AddEmployeeVC()
129
        addEmployeeVC.employee = self.employees[indexPath.row]
130
        addEmployeeVC.title = "Edit Employee"
131
        self.navigationController?.pushViewController(addEmployeeVC, animated: true)
132
    }
133
    
134
    func searchBar(_ searchBar: UISearchBar, textDidChange textSearched: String) {
135
        if(textSearched == "") {
136
            dismissKeyboard()
137
            isSearching = false
138
            employeeTable.reloadData()
139
        } else {
140
            isSearching = true
141
            searchResults = employees.filter {
142
                $0.name!.range(of: textSearched, options: .caseInsensitive) != nil
143
            }
144
            employeeTable.reloadData()
145
        }
146
    }
147
}



Service: service layer that uses Alamofire to handle the API requests.

Swift
 




x


1
import UIKit
2
import Alamofire
3
 
          
4
class EmployeeService {
5
    
6
    var url = "http://localhost:8080/employee/"
7
    
8
    func getAllEmployees(completion: @escaping (Result<[Employee], Error>) -> ()) {
9
        var request = URLRequest(url: URL(string: url)!)
10
        request.httpMethod = HTTPMethod.get.rawValue
11
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
12
        AF.request(request).validate(statusCode: 200..<300).responseJSON { response in
13
            if let err = response.error {
14
                completion(.failure(err))
15
                return
16
            }
17
            
18
            do {
19
                let employees = try JSONDecoder().decode([Employee].self, from: response.data!)
20
                completion(.success(employees))
21
                } catch let jsonError {
22
                completion(.failure(jsonError))
23
            }
24
        }.resume()
25
    }
26
    
27
    func createEmployee(employee: Employee, completion: @escaping (Result<Int, Error>) -> ()) {
28
        let encoder = JSONEncoder()
29
        let data = try! encoder.encode(employee)
30
        var request = URLRequest(url: URL(string: url)!)
31
        request.httpMethod = HTTPMethod.post.rawValue
32
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
33
        request.httpBody = data
34
        AF.request(request).validate(statusCode: 200..<300).responseJSON { response in
35
            if let err = response.error {
36
                completion(.failure(err))
37
                return
38
            }
39
            completion(.success(1))
40
        }.resume()
41
    }
42
    
43
    func updateEmployee(id: Int, employee: Employee, completion: @escaping (Result<Int, Error>) -> ()) {
44
        let encoder = JSONEncoder()
45
        let data = try! encoder.encode(employee)
46
        var request = URLRequest(url: URL(string: url + String(id))!)
47
        request.httpMethod = HTTPMethod.put.rawValue
48
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
49
        request.httpBody = data
50
        AF.request(request).validate(statusCode: 200..<300).responseJSON { response in
51
            if let err = response.error {
52
                completion(.failure(err))
53
                return
54
            }
55
            completion(.success(1))
56
        }.resume()
57
    }
58
    
59
    func deleteEmployee(id: Int, completion: @escaping (Result<Int, Error>) -> ()) {
60
        var request = URLRequest(url: URL(string: url + String(id))!)
61
        request.httpMethod = HTTPMethod.delete.rawValue
62
        AF.request(request).validate(statusCode: 200..<300).responseJSON { response in
63
            if let err = response.error {
64
                completion(.failure(err))
65
                return
66
            }
67
            completion(.success(1))
68
        }.resume()
69
    }
70
}



Now let's add the generated code to the project, you can press on Download Generated Code under the generated code section in CodeGen, then add the downloaded files to the project app folder, or you can copy-paste the generated code to the project. (Please note the file name should match the class name with .swift extension)

Add the EmployeeListViewController to a navigation bar in the TabBar class.

Swift
 




x


1
let employeeVC = UINavigationController(rootViewController: EmployeeListVC())
2
employeeVC.tabBarItem.title = "Employee"
3
viewControllers = [homeVC, employeeVC]



To keep the project simple and easy to maintain, divide it into groups (AddView, AddViewController, CellView, ListViewController, Model, Service).

To run the app, use one of the simulators provided, and press run.

com.app.tutorial

Running the application displays the two tab items Home and Employee. The Employee tab contains a table to list all the employees, search bar,  and a button to add a new employee.

As soon as you access the Employee tab, you get a Network error because we still don't have an API to handle the requests.

API requests

Create Spring Boot Rest API

Spring Boot reduces lots of development time and increases productivity. It avoids writing lots of boilerplate Codes, Annotations, and XML Configuration, however, just to get started, a lot of code is needed, but don't worry, Clowiz supports Spring Boot, and can generate the code for our API in a minute.

Prerequisite:

Create a new Spring Boot project using Spring Initializr:

  1. Leave the default settings as Maven Project, Java, and the version.
  2. In the Group field type: com.app
  3. In the Artifact field type: iosBackend
  4. From the Options, change the package name to com.app
  5. Search and add the following dependencies:
    • Spring web
    • Spring Data JPA
    • MySQL Driver
  6. Press on Generate to download the project.

Using any eclipse based IDE:

  1. Import the downloaded project. (File -> Import -> Existing Maven Project)
  2. Add the following to the "application.properties" file in the "src/main/resources package".
Properties files
 




x


1
# Local IP Address
2
server.address=127.0.0.1
3
spring.jpa.hibernate.ddl-auto=update
4
# MySQL Config
5
spring.datasource.url=jdbc:mysql://localhost:3306/employee?createDatabaseIfNotExist=true
6
spring.datasource.username=mysqlUserName
7
spring.datasource.password=mysqlPassword



We don't have to create a database manually; Spring JPA does that automatically, note the parameter  createDatabaseIfNotExist = true in the database URL.

Generate Spring Boot Artifacts

Back to Clowiz, press on the Spring Boot icon in the technologies section to generate the needed source code for the API.

For this tutorial, use the following generated artifacts:

Hibernate JPA Entity (The model).

Java
 




xxxxxxxxxx
1
69


1
package com.app.models;
2
 
          
3
import javax.persistence.*;
4
@Entity
5
@Table(name="employee")
6
public class Employee{
7
 
          
8
  @Id
9
  @Column(name="id")
10
  @GeneratedValue(strategy = GenerationType.IDENTITY)
11
  Integer id;
12
 
          
13
  @Column(name="name" , nullable=false)
14
  String name;
15
 
          
16
  @Column(name="email" , nullable=false)
17
  String email;
18
 
          
19
  @Column(name="salary" , nullable=false)
20
  Double salary;
21
 
          
22
 
          
23
  public void setId(Integer id){
24
    this.id=id;
25
  }
26
 
          
27
  public Integer getId(){
28
   return this.id;
29
  }
30
 
          
31
  public void setName(String name){
32
    this.name=name;
33
  }
34
 
          
35
  public String getName(){
36
   return this.name;
37
  }
38
 
          
39
  public void setEmail(String email){
40
    this.email=email;
41
  }
42
 
          
43
  public String getEmail(){
44
   return this.email;
45
  }
46
 
          
47
  public void setSalary(Double salary){
48
    this.salary=salary;
49
  }
50
 
          
51
  public Double getSalary(){
52
   return this.salary;
53
  }
54
  @Override
55
  public String toString(){
56
    StringBuffer buf=new StringBuffer();
57
    buf.append(this.name).append(" ");
58
    return buf.toString();
59
  }
60
 
          
61
  @Override
62
  public boolean equals(Object obj) {
63
    if (obj == null) {
64
      return false;
65
    }
66
    return this.getId() == ((Employee) obj).getId();
67
  }
68
 
          
69
}





SpringData Service.

Java
 




xxxxxxxxxx
1
13


1
package com.app.repositories;
2
 
          
3
import java.util.List;
4
import org.springframework.data.jpa.repository.JpaRepository;
5
import org.springframework.stereotype.Service;
6
import com.app.models.Employee;
7
 
          
8
@Service
9
public interface EmployeeService extends JpaRepository<Employee, Integer> {
10
    public List<Employee> findByName(String name);
11
    public List<Employee> findByEmail(String email);
12
    public List<Employee> findBySalary(String salary);
13
}



Mature Spring RestController.

Java
 




xxxxxxxxxx
1
72


1
package com.app.controllers; 
2
 
          
3
import java.util.*;
4
import org.springframework.beans.factory.annotation.Autowired;
5
import org.springframework.http.*;
6
import org.springframework.web.bind.annotation.*;
7
 
          
8
import com.app.models.Employee;
9
import com.app.repositories.EmployeeService;
10
 
          
11
@RestController
12
@RequestMapping("/employee")
13
public class EmployeeController {
14
 
          
15
    @Autowired
16
    EmployeeService employeeService;
17
 
          
18
    @RequestMapping(method = RequestMethod.OPTIONS)
19
    ResponseEntity<?> options() {
20
      // @formatter:off
21
      return ResponseEntity.ok().allow(
22
               HttpMethod.GET,
23
               HttpMethod.POST,
24
               HttpMethod.HEAD,
25
               HttpMethod.OPTIONS,
26
               HttpMethod.PUT,
27
               HttpMethod.DELETE).
28
               build(); 
29
      // @formatter:on
30
    }
31
 
          
32
    @GetMapping
33
    public ResponseEntity<List<Employee>> getAll() {
34
        return ResponseEntity.ok(this.employeeService.findAll());
35
    }
36
 
          
37
    @PostMapping
38
    public ResponseEntity<Employee> insert(@RequestBody Employee employee) {
39
        Employee save = this.employeeService.save(employee);
40
        return ResponseEntity.ok(save);
41
    }
42
 
          
43
    @GetMapping(value = "/{id}")
44
    public ResponseEntity<Employee> find(@PathVariable("id") int id) {
45
        Optional<Employee> object = this.employeeService.findById(id);
46
        if (object.isPresent()) {
47
            return ResponseEntity.ok(object.get());
48
        }
49
        return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
50
    }
51
 
          
52
    @DeleteMapping(value="/{id}")
53
    public ResponseEntity<Employee> delete(@PathVariable int id){
54
        Optional<Employee> object = this.employeeService.findById(id);
55
        if(object.isPresent()) {
56
            this.employeeService.deleteById(id);
57
            return ResponseEntity.noContent().build();
58
        }
59
        return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
60
    }
61
 
          
62
    @PutMapping(value="/{id}")
63
    public ResponseEntity<Employee> save(@PathVariable int id, @RequestBody Employee employee){
64
        Optional<Employee> object = this.employeeService.findById(id);
65
        if(object.isPresent()) {
66
            employee.setId(id);
67
            this.employeeService.save(employee);
68
            return ResponseEntity.noContent().build();
69
        }
70
        return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
71
    }
72
}



As we did in the iOS project, copy-paste the generated code to the right packages with the correct classes names, or you can download it by pressing Download Generated Code.

To keep the project simple and easy to maintain, divide it into packages (controllers, models, repositories).

Check that the URL in the iOS Service class matches with the Spring Boot properties file server IP.

To run the project, open the IosBackendApplication.java class, right-click and Run As Java Application.

You can test it using any tool like Postman, or using any browser, visit: http://127.0.0.1/employee this should return an empty list [] as we don't have any data in the database.

Running the App

After running the Spring Boot API, rerun the iOS project.

  1. Go to the Employee tab
  2. Press on the Add button
  3. Fill in Employee data
  4. Press on save
  5. Tap on a row to edit it
  6. Swipe a row to delete it

failure message


Topics:
code generation ,ios ,java ,spring boot ,swift ,tutorial ,web dev

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}