Разработка Java-проекта с Jmix AI Assistant, часть 2

от автора

В первой части статьи с помощью инструмента Jmix AI Assistant начато создание системы для проведения онлайн курсов.

Были сгенерированы сценарии использования (use cases), разработана UML-диаграмма в формате PlantUML для этих use cases, разработана доменная модель для системы и ее реализация на JMIX. Далее все классы разбиты по пакетам.

Продолжим эксперименты по разработке кода с помощью Jmix AI Assistant, включая следующие:

  • Генерация класса, заполняющего доменную модель тестовыми данными

  • Генерация REST API для модели домена, включая создание контроллеров и REST сервисов

  • Генерация CRUD-экранов пользовательского интерфейса

Генерация класса, заполняющего доменную модель тестовыми данными

Пишем очередной запрос для Jmix AI Assistant:

Сгенерируй класс, заполняющий доменную модель тестовыми данными.

Создай 2-3 студентов, добавь 2 курса и несколько материалов,

2 теста с 2-3 вопросами, запиши студентов на курс.

Выведи информацию о всех курсах.

Для каждого курса выводи список студентов (имя, фамилия, email), список материалов и список тестов.

Ответ должен содержать только код.

В качестве пакета используй ru.rsa.mcc.eduplatform.

Получаем ответ от Jmix AI Assistant:

package ru.rsa.mcc.eduplatform;  import ru.rsa.mcc.eduplatform.model.user.Student; import ru.rsa.mcc.eduplatform.model.course.Course; import ru.rsa.mcc.eduplatform.model.course.Module; import ru.rsa.mcc.eduplatform.model.content.Material; import ru.rsa.mcc.eduplatform.model.assessment.Test; import ru.rsa.mcc.eduplatform.model.assessment.Question;  import java.time.LocalDate; import java.util.ArrayList; import java.util.List;  public class TestDataGenerator {      public static void main(String[] args) {         // Create students         Student student1 = new Student();         student1.setUsername("john_doe");         student1.setPassword("password123");         student1.setEmail("john.doe@example.com");         student1.setStudentId("S001");         student1.setEnrollmentDate(LocalDate.now());          Student student2 = new Student();         student2.setUsername("jane_smith");         student2.setPassword("password123");         student2.setEmail("jane.smith@example.com");         student2.setStudentId("S002");         student2.setEnrollmentDate(LocalDate.now());          Student student3 = new Student();         student3.setUsername("alice_jones");         student3.setPassword("password123");         student3.setEmail("alice.jones@example.com");         student3.setStudentId("S003");         student3.setEnrollmentDate(LocalDate.now());          // Create courses         Course course1 = new Course();         course1.setTitle("Introduction to Programming");         course1.setDescription("Learn the basics of programming.");          Course course2 = new Course();         course2.setTitle("Advanced Java");         course2.setDescription("Deep dive into Java programming.");          // Create materials         Material material1 = new Material();         material1.setTitle("Java Basics");         material1.setType("Video");         material1.setData("URL to Java Basics Video");         material1.setDuration(60);          Material material2 = new Material();         material2.setTitle("OOP Concepts");         material2.setType("Document");         material2.setData("URL to OOP Concepts Document");         material2.setDuration(45);          // Create tests         Test test1 = new Test();         test1.setTitle("Java Basics Test");         test1.setDate(LocalDate.now());         test1.setDuration(30);          Question question1 = new Question();         question1.setText("What is Java?");         question1.setOptions(List.of("Programming Language", "Coffee", "Animal"));         question1.setCorrectAnswer("Programming Language");          Question question2 = new Question();         question2.setText("What is OOP?");         question2.setOptions(List.of("Object-Oriented Programming", "Open Office Protocol", "Online Order Processing"));         question2.setCorrectAnswer("Object-Oriented Programming");          test1.setQuestions(List.of(question1, question2));          Test test2 = new Test();         test2.setTitle("Advanced Java Test");         test2.setDate(LocalDate.now());         test2.setDuration(45);          Question question3 = new Question();         question3.setText("What is polymorphism?");         question3.setOptions(List.of("Many forms", "Single form", "No form"));         question3.setCorrectAnswer("Many forms");          test2.setQuestions(List.of(question3));          // Assign students to courses         List<Student> studentsCourse1 = new ArrayList<>();         studentsCourse1.add(student1);         studentsCourse1.add(student2);          List<Student> studentsCourse2 = new ArrayList<>();         studentsCourse2.add(student3);          // Assign materials and tests to modules         Module module1 = new Module();         module1.setTitle("Module 1");         module1.setDescription("Basic Module");         module1.setMaterials(List.of(material1, material2));         module1.setTests(List.of(test1));          Module module2 = new Module();         module2.setTitle("Module 2");         module2.setDescription("Advanced Module");         module2.setMaterials(List.of(material2));         module2.setTests(List.of(test2));          // Assign modules to courses         course1.setModules(List.of(module1));         course2.setModules(List.of(module2));          // Print course information         printCourseInfo(course1, studentsCourse1);         printCourseInfo(course2, studentsCourse2);     }      private static void printCourseInfo(Course course, List<Student> students) {         System.out.println("Course: " + course.getTitle());         System.out.println("Description: " + course.getDescription());         System.out.println("Students Enrolled:");         for (Student student : students) {             System.out.println(" - " + student.getUsername() + " (" + student.getEmail() + ")");         }         System.out.println("Modules:");         for (Module module : course.getModules()) {             System.out.println("  Module: " + module.getTitle());             System.out.println("  Materials:");             for (Material material : module.getMaterials()) {                 System.out.println("   - " + material.getTitle() + " (" + material.getType() + ")");             }             System.out.println("  Tests:");             for (Test test : module.getTests()) {                 System.out.println("   - " + test.getTitle());             }         }         System.out.println();     } }

Этот код настраивает простой генератор тестовых данных для нашей образовательной платформы. Он создает студентов, курсы, модули, материалы и тесты, а затем распечатывает информацию о курсе, включая зарегистрированных студентов, материалы и тесты.

Генерация REST API для модели домена, включая создание контроллеров и REST сервисов

Пишем очередной запрос Jmix AI Assistant:

Сгенерировать REST-запросы, контроллеры и сервисы

Получаем следующий ответ от Jmix AI Assistant:

Чтобы в приложении Jmix предоставить доступ к нашей модели домена через REST API, необходимо создать REST контроллеры и сервисы. Ниже приведено пошаговое решение по настройке конечных точек REST для управления учащимися, курсами и связанными объектами.

Пошаговое решение

  1. Создание сервисного уровня:

    • Сервисы будут обрабатывать бизнес логику и взаимодействовать с базой данных с помощью DataManager.

  2. Создание контроллеров REST:

    • Контроллеры будут предоставлять доступ к конечным точкам REST и использовать сервисный уровень для выполнения REST-запросов.

Уровень сервиса

StudentService.java

package ru.rsa.mcc.eduplatform.service;  import io.jmix.core.DataManager; import io.jmix.core.SaveContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.rsa.mcc.eduplatform.model.user.Student;  import java.util.List;  @Service public class StudentService {      @Autowired     private DataManager dataManager;      public List<Student> getAllStudents() {         return dataManager.load(Student.class).all().list();     }      public Student saveStudent(Student student) {         return dataManager.save(student);     }      public void deleteStudent(Student student) {         dataManager.remove(student);     } }

CourseService.java

package ru.rsa.mcc.eduplatform.service;  import io.jmix.core.DataManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.rsa.mcc.eduplatform.model.course.Course;  import java.util.List;  @Service public class CourseService {      @Autowired     private DataManager dataManager;      public List<Course> getAllCourses() {         return dataManager.load(Course.class).all().list();     }      public Course saveCourse(Course course) {         return dataManager.save(course);     }      public void deleteCourse(Course course) {         dataManager.remove(course);     } }

REST контроллеры

StudentController.java

package ru.rsa.mcc.eduplatform.controller;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import ru.rsa.mcc.eduplatform.model.user.Student; import ru.rsa.mcc.eduplatform.service.StudentService;  import java.util.List;  @RestController @RequestMapping("/api/students") public class StudentController {      @Autowired     private StudentService studentService;      @GetMapping     public List<Student> getAllStudents() {         return studentService.getAllStudents();     }      @PostMapping     public Student createStudent(@RequestBody Student student) {         return studentService.saveStudent(student);     }      @DeleteMapping("/{id}")     public void deleteStudent(@PathVariable String id) {         Student student = studentService.getAllStudents().stream()                 .filter(s -> s.getId().toString().equals(id))                 .findFirst()                 .orElseThrow(() -> new IllegalArgumentException("Student not found"));         studentService.deleteStudent(student);     } }

CourseController.java

package ru.rsa.mcc.eduplatform.controller;  import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import ru.rsa.mcc.eduplatform.model.course.Course; import ru.rsa.mcc.eduplatform.service.CourseService;  import java.util.List;  @RestController @RequestMapping("/api/courses") public class CourseController {      @Autowired     private CourseService courseService;      @GetMapping     public List<Course> getAllCourses() {         return courseService.getAllCourses();     }      @PostMapping     public Course createCourse(@RequestBody Course course) {         return courseService.saveCourse(course);     }      @DeleteMapping("/{id}")     public void deleteCourse(@PathVariable String id) {         Course course = courseService.getAllCourses().stream()                 .filter(c -> c.getId().toString().equals(id))                 .findFirst()                 .orElseThrow(() -> new IllegalArgumentException("Course not found"));         courseService.deleteCourse(course);     } }

Объяснение:

  • Сервисный уровень: обрабатывает бизнес логику и взаимодействия с базой данных с помощьюDataManager.

  • Контроллеры REST: предоставляют конечные точки для операций CRUD с объектами Student и Course.

  • Конечные точки:

    • GET /api/students: Извлечь всех студентов.

    • POST /api/students: Создать нового студента.

    • DELETE /api/students/{id}: Удалить студента по идентификатору.

    • GET /api/courses: Извлечь все курсы.

    • POST /api/courses: Создать новый курс.

    • DELETE /api/courses/{id}: Удалить курс по идентификатору.

Эти классы предоставляют базовый REST API для управления учащимися и курсами в вашем приложении Jmix. Вы можете расширить его, добавив дополнительные конечные точки и службы для других объектов по мере необходимости.

Генерация CRUD-экранов для сущностей

Пишем следующий запрос Jmix AI Assistant:

Сгенерировать CRUD-экраны для всех сущностей

Получаем такой ответ от Jmix AI Assistant:

Чтобы создать CRUD-экраны для всех объектов в Jmix, вы можете использовать Jmix Studio, которая предоставляет мастер создания представлений из шаблонов. Ниже приведено пошаговое руководство по созданию этих экранов с помощью Jmix Studio.

Пошаговое решение

  1. Откройте Jmix Studio:

    • Запустите свой проект Jmix в IntelliJ IDEA с установленной Jmix Studio.

  2. Перейдите к сущности:

    • В окне инструмента Jmix найдите сущность, для которой вы хотите создать CRUD-экраны.

  3. Воспользуйтесь мастером создания представлений (View):

    • Щелкните правой кнопкой мыши на сущности и выберите New -> View.

    • В качестве альтернативы вы можете выбрать сущность и нажать Viewsна верхней панели конструктора сущностей.

  4. Выберите шаблон:

    • Мастер представит список шаблонов. Выберите подходящий шаблон для просмотра в режиме CRUD.

  5. Настройте View:

    • Вы можете изменить автоматически созданные свойства View.

    • В пунктах меню Entity list view fetch plan и Entity detail view fetch выберите данные, которые будут отображаться в представлениях. Вы можете использовать встроенные планы выборки или создать свои собственные.

  6. Завершите работу Мастера:

    • Нажмите кнопку Finish, чтобы сгенерировать XML-дескриптор представления и контроллер представления.

    • Файл пакета сообщений будет обновлен, и в главное меню будет добавлен новый пункт меню, если вы создаете list view.

  7. Настройка представлений:

    • Используйте конструктор представлений для дальнейшей настройки ваших представлений по мере необходимости.

Пример сгенерированного кода

Вот пример того, как может выглядеть сгенерированное представление списка для сущности Student:

student-list-view.xml

<view xmlns="http://jmix.io/schema/flowui/view">     <data>         <collection id="studentsDc"                     class="ru.rsa.mcc.eduplatform.model.user.Student"                     fetchPlan="_base">             <loader id="studentsDl">                 <query>                     <![CDATA[select e from Student e]]>                 </query>             </loader>         </collection>     </data>     <facets>         <dataLoadCoordinator auto="true"/>     </facets>     <layout>         <hbox id="buttonsPanel" classNames="buttons-panel">             <button id="createBtn" action="studentsDataGrid.create"/>             <button id="editBtn" action="studentsDataGrid.edit"/>             <button id="removeBtn" action="studentsDataGrid.remove"/>         </hbox>         <dataGrid id="studentsDataGrid"                   width="100%"                   minHeight="20em"                   dataContainer="studentsDc">             <actions>                 <action id="create" type="list_create"/>                 <action id="edit" type="list_edit"/>                 <action id="remove" type="list_remove"/>             </actions>             <columns>                 <column property="username"/>                 <column property="email"/>                 <column property="studentId"/>                 <column property="enrollmentDate"/>             </columns>         </dataGrid>     </layout> </view> 

StudentListView.java

package ru.rsa.mcc.eduplatform.view.student;  import io.jmix.flowui.view.*; import ru.rsa.mcc.eduplatform.model.user.Student;  @ViewController("student-list-view") @ViewDescriptor("student-list-view.xml") @Route("students") public class StudentListView extends StandardListView<Student> { } 

Объяснение:

  • Мастер создания представлений: Мастер Jmix Studio упрощает создание экранов CRUD, предоставляя шаблоны и параметры конфигурации.

  • Настройка: После создания экранов вы можете настроить их с помощью конструктора представлений.

  • Сгенерированный код: Сгенерированный код: В примере показано представление list view для сущности Student, включая табличное представление данных с действиями по созданию, редактированию и удалению сущностей.

Такой подход позволяет вам быстро создавать и настраивать CRUD-экраны для всех ваших объектов в приложении Jmix.

Источники:

Заключение

В рамках этой заметки описаны эксперименты по разработке кода с помощью Jmix AI Assistant, включая следующие:

  • Генерация класса, заполняющего доменную модель тестовыми данными

  • Реализация REST API для модели домена, включая создание контроллеров и REST сервисов

  • Генерация CRUD-экранов пользовательского интерфейса

Код, сгенерированный Jmix AI Assistant, вполне работоспособный. Естественно хотелось бы чтобы Jmix AI Assistant был интегрирован в Jmix Studio.

В статье Jmix AI Assistant — ваш помощник в освоении Jmix озвучены планы разработчиков:

Далее мы планируем интегрировать ассистента в Jmix Studio. Он сможет по простым запросам создавать сущности, экраны и добавлять компоненты: «Сделай экраны для этой сущности», «Добавь слушатели для кнопки». Возможно, добавим голосовой ввод команд. 


ссылка на оригинал статьи https://habr.com/ru/articles/908736/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *