Send your request Join Sii

The article is about the realities of using ChatGPT to automate the writing of Java code, with a specific example and several conclusions on how ChatGPT would change the development market. I want to show you how, in our day, we can write every layer of Spring framework application without writing any lines of code by hand.

Introduction

There are opposed opinions among developers and IT company leaders regarding the current and future use of AI tools for code generation. Some predict that AI will take over a significant portion of work shortly, while others don’t see GPT as a human competitor, not even in the next quarter-century.

To support their argument that AI can effectively replace humans, the first group provides a couple of video examples where a simple application is written in real-time using ChatGPT in just 10 minutes. They also mention historical parallels with automation in other fields, where progress reduced human involvement by 5–7 times.

The second camp opposes the first by presenting the argument that people can write better code without any assistance from AI. They provide various arguments for the indispensability of humans in the development process, with the most popular ones being:

  • The important role of human communication;
  • The difficulties of formulations the requirements by the client;
  • The creative process needs, which can only be performed directly by a human.
Developers are excited about the prospects that ChatGPT opens up for us
Fig. 1 Developers are excited about the prospects that ChatGPT opens up for us

So, who is right? When will artificial intelligence replace all of us? And what is the most appropriate comparison for ChatGPT today?

Just a few words about theory to understand practice

To process a code-writing request, ChatGPT goes through a vast amount of data, including open-source code repositories where elements of the seeking solution or the entire solution likely exist. Wire internal graph relying on this data, the model navigates its “labyrinth,” attempting to predict the probability of determining the appropriateness of lexical units (variables, methods, code snippets) that, when sequentially arranged, make up the application code in response to our request.

However, the result is not stable. The reason is that the model essentially “rolls the dice” each time when making predictions for this probability. While considering the probability, it doesn’t guarantee choosing the element or combination of elements with the highest predicted probability. Often, by slightly changing the request or introducing an additional parameter, or even without making any changes, we can obtain a different, sometimes significantly different, result from the previous one.

What does work with ChatGPT look like?

You can take a large task and feed it to ChatGPT as it is. It will process it and provide a solution. But if we try to make a big request, we will receive:

  1. More abstract solutions that will require customization;
  2. More unsuitable solution that will require rework;
  3. In the end, the suggested option is not guaranteed to work.

As a result, you will receive long nights of debug sessions.

In practice, a large task is typically divided into smaller, more specific, and narrower sub-tasks, which are then presented to ChatGPT.

So, let’s divide the creation of all layers of the Spring application and feed it to ChatGPT.

Practice

When creating a typical CRUD controller, a developer usually does several things.

  1. Create Entity;
  2. Make migration of data to DB;
  3. Create DTO for the Entity;
  4. Create Repository layer;
  5. Create Service layer;
  6. Create a Controller layer.

Create Entity

Prompt to ChatGPT:

“create for me the entity class of User with Long id, firstName, lastName, phoneNumber, UUID keycloakId, @ManyToOne relation with class Department.”

The response:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;
    private String lastName;
    private String phoneNumber;
    private UUID keycloakId;

    @ManyToOne
    @JoinColumn(name = "department_id") // Assuming a foreign key column named 'department_id'
    private Department department;

    // Constructors, getters, and setters

    public User() {
    }

    public User(String firstName, String lastName, String phoneNumber, UUID keycloakId, Department department) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.phoneNumber = phoneNumber;
        this.keycloakId = keycloakId;
        this.department = department;
    }

    // Getters and setters for all fields

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public UUID getKeycloakId() {
        return keycloakId;
    }

    public void setKeycloakId(UUID keycloakId) {
        this.keycloakId = keycloakId;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }
}

But we want to make the same result but using Lombok:

Using Lombok to create the entity class
Fig. 2 Using Lombok to create the entity class

Create DTO

Prompt to ChatGPT:

“Can you create a DTO class for this entity?”

Response from ChatGPT:

public class UserDTO {
    private Long id;
    private String firstName;
    private String lastName;
    private String phoneNumber;
    private UUID keycloakId;
    Private Long departmentId; // Assuming you want to transfer the department ID

    public UserDTO() {
    }

    public UserDTO(Long id, String firstName, String lastName, String phoneNumber, UUID keycloakId, Long departmentId) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.phoneNumber = phoneNumber;
        this.keycloakId = keycloakId;
        this.departmentId = departmentId;
    }

    // Getters and setters for all fields

    }

Create Repository

Prompt to ChatGPT:

“Can you create a repository for this entity?”

Response from ChatGPT:

import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    // You can add custom query methods here if needed
}

Create Service

Prompt to ChatGPT:

Can you create for this entity CRUD Service with the next methods:

  1. Received pageable list of users;
  2. Receive user by Id;
  3. Delete User by Id;
  4. Create a new User.

Response from ChatGPT:

@Service
public class UserService {

    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    // Method to receive a pageable list of users
    public Page<User> getAllUsers(Pageable pageable) {
        return userRepository.findAll(pageable);
    }

    // Method to receive a user by Id
    public Optional<User> getUserById(Long userId) {
        return userRepository.findById(userId);
    }

    // Method to delete a user by Id
    public void deleteUserById(Long userId) {
        userRepository.deleteById(userId);
    }

    // Method to create a new user
    public User createUser(User user) {
        return userRepository.save(user);
    }
}

Make migration of data to DB

Prompt to ChatGPT:

“Can you create the migration of this entity to the database?”

Response from ChatGPT:

-- Create the User table
CREATE TABLE user (
    id BIGINT PRIMARY KEY AUTO_INCREMENT, -- Use the appropriate data type for your database
    first_name VARCHAR(255) NOT NULL,
    last_name VARCHAR(255) NOT NULL,
    phone_number VARCHAR(20),
    keycloak_id UUID, -- Use the appropriate data type for UUID in your database
    department_id BIGINT, -- Use the appropriate data type for the foreign key reference
    FOREIGN KEY (department_id) REFERENCES department(id) -- Make sure to reference the correct table and column names
);

Create Controller

Prompt to ChatGPT:

“Can you create a Controller for this Service?”

Response from ChatGPT:

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    // Get a pageable list of users
    @GetMapping
    public ResponseEntity<Page<User>> getAllUsers(Pageable pageable) {
        Page<User> users = userService.getAllUsers(pageable);
        return new ResponseEntity<>(users, HttpStatus.OK);
    }

    // Get a user by Id
    @GetMapping("/{userId}")
    public ResponseEntity<User> getUserById(@PathVariable Long userId) {
        return userService.getUserById(userId)
                .map(user -> new ResponseEntity<>(user, HttpStatus.OK))
                .orElseGet(() -> new ResponseEntity<>(HttpStatus.NOT_FOUND));
    }

    // Create a new user
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User createdUser = userService.createUser(user);
        return new ResponseEntity<>(createdUser, HttpStatus.CREATED);
    }

    // Delete a user by Id
    @DeleteMapping("/{userId}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long userId) {
        userService.deleteUserById(userId);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
}

Create Mock JSON file of created data

Prompt to ChatGPT:

“Can you create from the DTO class json file with mock data?”

Response from ChatGPT:

[
   {
      "id":1,
      "firstName":"John",
      "lastName":"Doe",
      "phoneNumber":"123-456-7890",
      "keycloakId":"5e7e4196-4a10-11ec-8d3d-0242ac130003",
      "departmentId":1
   },
   {
      "id":2,
      "firstName":"Alice",
      "lastName":"Smith",
      "phoneNumber":"987-654-3210",
      "keycloakId":"6d7e4196-4a10-11ec-8d3d-0242ac130003",
      "departmentId":2
   },
   {
      "id":3,
      "firstName":"Bob",
      "lastName":"Johnson",
      "phoneNumber":"555-555-5555",
      "keycloakId":"7d7e4196-4a10-11ec-8d3d-0242ac130003",
      "departmentId":1
   }
]

Create Unit tests for Service

Prompt to ChatGPT:

“Can you create unit tests for the service class?”

 Response from ChatGPT:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;

import java.util.Optional;

import static org.mockito.Mockito.*;

public class UserServiceTest {

    @InjectMocks
    private UserService userService;

    @Mock
    private UserRepository userRepository;

    @BeforeEach
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testGetAllUsers() {
        // Mock data
        Pageable pageable = PageRequest.of(0, 10);
        Page<User> users = mock(Page.class);

        when(userRepository.findAll(pageable)).thenReturn(users);

        Page<User> result = userService.getAllUsers(pageable);

        verify(userRepository, times(1)).findAll(pageable);
    }

    @Test
    public void testGetUserById() {
        // Mock data
        Long userId = 1L;
        User user = new User();
        when(userRepository.findById(userId)).thenReturn(Optional.of(user));

        Optional<User> result = userService.getUserById(userId);

        verify(userRepository, times(1)).findById(userId);
    }

    @Test
    public void testGetUserById_NotFound() {
        // Mock data
        Long userId = 1L;
        when(userRepository.findById(userId)).thenReturn(Optional.empty());

        Optional<User> result = userService.getUserById(userId);

        verify(userRepository, times(1)).findById(userId);
    }

    @Test
    public void testDeleteUserById() {
        // Mock data
        Long userId = 1L;

        userService.deleteUserById(userId);

        verify(userRepository, times(1)).deleteById(userId);
    }

    @Test
    public void testCreateUser() {
        // Mock data
        User user = new User();

        when(userRepository.save(user)).thenReturn(user);

        User result = userService.createUser(user);

        verify(userRepository, times(1)).save(user);
    }
}

Print project structure for a better understanding of what we generated

Prompt to ChatGPT:

“Can you generate the whole code structure of this project?”

Response from ChatGPT:

response from chatgpt

Pros and cons

Based on the above, I can determine the pros and cons of using AI at the current level at which we have it.

It can be useful for increasing the time spent coding. Comparing the example in this article, I can say that if I had to write this structure by hand, I think that I would spend 2 times more. I can say that the model layer increases the number of classes, so the difference between hand programming and programming using AI will increase.

The other plus is that ChatGPT, when it generates something, describes to you each tool that it used and tells you for what purpose it was used. Also, you can ask it to remove some tools or use the other one. 

The good thing is that ChatGPT, within one chat, remembers the whole story of your “conversation.” And it creates the answer, remembering chat history.

You can ask everything: generate whole class, method, script for CI/CD pipeline, Jenkins script, application properties file, how to create docker files, etc.

But the main problem is that you can’t trust it because chatGPT doesn’t have a problem with lying. It can generate something and say it will surely work, but that will be wrong. Every time we ask something, we must remember that every request, even the same one, will return a different response. So, in any case, the developer must decide what the result is supposed to look like and be responsible for the project build, tests run, whether the code contains any bugs, and so on.

Conclusion

So, in the end, what is ChatGPT essentially? Considering its behavior and functioning, ChatGPT is now more like a genie in a lamp. It has a good foundation, excellent powerful tools, and can find the right solution, but the request must be extremely precise to get the desired result. Even if you are accurate, it’s not guaranteed that you will succeed on the first try, and something undesirable may still come out.

Even though not everything is smooth with coding in ChatGPT at the moment, this technology can be integrated with plugins for IDEs. In the future, once they are refined, they can assist developers in writing code much better than ChatGPT does now in a question-and-answer format.

Currently, we have a production-ready solution from Microsoft. I am talking about Github Copilot, which can suggest and generate code blocks for you based on the method name. This tool is not the same as ChatGPT, but it is also very useful and decreases the time of coding some basic solutions in projects. And again, they can assist but not write the whole project for the developer, replacing them.

My predictions

Will ChatGPT eventually leave developers without a job? – No! Currently, ChatGPT in production is not an engineer but an engineer’s tool.

Will it automate the process of writing code over time and significantly reduce this stage of development? – Yes, definitely.

Rating:
Author
Avatar
Oleksandr Turchanovskyi

He is a software developer with, in summary, 3.5 years of professional experience. He’s working in Sii on the position Software Engineer. Oleksandr’s main course is improving himself in Java + Spring tech stack. He’s interested in building systems from scratch and resolving non-trivial tasks

Leave a comment

Your email address will not be published. Required fields are marked *

You might also like

More articles

Don't miss out

Subscribe to our blog and receive information about the latest posts.

Get an offer

If you have any questions or would like to learn more about our offer, feel free to contact us.

Send your request Send your request

Natalia Competency Center Director

Get an offer

Join Sii

Find the job that's right for you. Check out open positions and apply.

Apply Apply

Paweł Process Owner

Join Sii

SUBMIT

Ta treść jest dostępna tylko w jednej wersji językowej.
Nastąpi przekierowanie do strony głównej.

Czy chcesz opuścić tę stronę?