Статьи

Простые RESTful-услуги в Glassfish Pt 2

Во второй части этой статьи мы собираемся создать управляемый данными веб-сервис, который будет возвращать JSON и XML клиенту, а затем с помощью jQuery добавить новый элемент в базу данных и отобразить его на нашей странице.

В первой части мы рассмотрели создание простых веб-сервисов, а теперь мы собираемся сделать что-то более практичное и интересное. Мы начнем с того места, где мы остановились, с исходным кодом, как это было в конце части 1, которую вы можете скачать отсюда ( restwebdemo_pt1 ), если хотите следовать. Если нет, окончательный исходный код можно скачать отсюда ( restwebdemo_pt2 ).

  1. Прежде всего, мы собираемся изменить менеджера сущностей, который доступен для внедрения в область запроса. Для этого откройте DataRepositoryProducer.java и измените аннотацию @ConversationScoped в методе getEntityManager () на @RequestScoped. Причина этого задокументирована в разделе «Меньше разговоров» .
  2. Далее мы собираемся создать простой дао для объектов Course, и единственная причина сделать это — продемонстрировать интеграцию CDI и способность наслоить ваш код. Создайте новый класс с именем CourseDao со следующим кодом.
    package org.fluttercode.restwebdemo.bean;

    @Stateless
    @LocalBean
    public class CourseDao {

    @Inject @DataRepository
    private EntityManager entityManager;

    public void save(Course course) {
    entityManager.persist(course);
    }

    public Course update(Course course) {
    return entityManager.merge(course);
    }

    public Course find(Long id) {
    return entityManager.find(Course.class, id);
    }
    }

    Это просто внедряет entityManager и использует его для поиска, сохранения и обновления объектов курса.

  3. Теперь создайте новый компонент CourseService, который будет обрабатывать веб-сервисы. Для начала мы хотим сделать его EJB без учета состояния и ввести курс Dao. Мы собираемся начать с повторной реализации метода, чтобы вернуть имя курса для данного идентификатора.
    @Path("courseName/{id}")
    @GET
    public String getCourseName(@PathParam("id") Long id) {
    Course course = courseDao.find(id);
    if (course == null) {
    return "Course not found";
    } else {
    return course.getTitle();
    }
    }

Чтобы увидеть этот метод в действии, разверните приложение и перейдите по адресу http: // localhost: 8080 / restwebdemo / rest / course / courseName / 126 . Теперь мы знаем, что все работает и подключены вместе, мы можем посмотреть на добавление некоторых новых функций.

Давайте начнем с возврата курса с заданным идентификатором из сервиса. Это довольно просто, учитывая то, что мы уже знаем. Теперь единственное, что нужно определить — это какой формат вернуть объект и преобразовать его в этот тип. К счастью, Java EE уже предоставляет JAXB, который может взять граф объектов и преобразовать его в XML для нас, пока мы аннотируем классы аннотациями, чтобы реализация JAXB знала, как преобразовать его. Те же самые аннотации могут использоваться автором тела, который обрабатывает JSON.

Сначала мы аннотируем курс и сделаем пару изменений, которые нам нужны. Далее мы создадим методы для возврата объекта Cource из сервиса в формате XML или JSON.

  1. Откройте класс Course и добавьте в него следующие аннотации.

    @Entity
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Course extends BaseEntity {
    ...
    ...
    }

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

    Это простой пример, поэтому мы не хотим сериализовать учитель или зарегистрированные свойства, которые мы можем сделать, пометив их атрибутами @XmlTransient. Также удалите аннотацию @NotNull из атрибута учителя, так как она понадобится нам позже. Следующий код показывает поля с аннотациями JAXB и JPA. JAXB (как JPA) использует соглашения по умолчанию для полей, которые не имеют аннотаций:

    @Column(length = 32, nullable = false)
    @Size(max = 32)
    @NotEmpty(message = "title is required")
    private String title;

    @Column(length = 8, nullable = false)
    @Size(max = 8 )
    @NotEmpty(message = "code is required")
    private String code;

    @ManyToOne(fetch = FetchType.LAZY)
    @XmlTransient
    private Teacher teacher;

    @ManyToMany(mappedBy = "enrolled")
    @XmlTransient
    private List<Student> students = new ArrayList<Student>();

    Мы просто используем простую модель JAXB для примера, поэтому мы не включаем классы Teacher и Student.

  2. Теперь в нашем классе CourseService мы создадим методы для возврата сущности курса и создадим один для JSON и один для XML.

    @Path("find/{id}/xml")
    @GET
    @Produces(MediaType.APPLICATION_XML)
    public Course getCourseAsXml(@PathParam("id") Long id) {
    return courseDao.find(id);
    }

    @Path("find/{id}/json")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Course getCourseAsJson(@PathParam("id") Long id) {
    return courseDao.find(id);
    }
  3. (примечание: на этом этапе мне пришлось переключиться на использование Hibernate в качестве поставщика JPA, поскольку JAXB не понравился интерфейс EclipseLink, используемый для передачи свойств. Это можно сделать с помощью инструмента обновления Glassfish).
    Если вы повторно развернете приложение и перейдете по адресу http: // localhost: 8080 / restwebdemo / rest / course / find / 1 / json, вам будет предложено сохранить файл, или он отобразит текст, но содержимое должно быть примерно таким: :

    {"createdOn":"2010-08-27T16:36:57.015-04:00",
    "id":"1",
    "modifiedOn":"2010-08-27T16:36:57.015-04:00",
    "title":"Computing for Beginners",
    "code":"CS101"}

    или если вы перейдете по адресу http: // localhost: 8080 / restwebdemo / rest / course / find / 1 / xml, вы получите версию XML:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <course>
    <createdOn>2010-08-27T16:36:57.015-04:00</createdOn>
    <id>1</id>
    <modifiedOn>2010-08-27T16:36:57.015-04:00</modifiedOn>
    <title>Computing for Beginners</title>
    <code>CS101</code>
    </course>

    Теперь мы можем получить объекты из нашего веб-сервиса, мы должны посмотреть на создание объектов из сервиса. Мы добавляем новый метод, который принимает заголовок и значения кода, создает новый курс с этими значениями и сохраняет его с помощью courseDao.

    @Path("create")
    @PUT
    @Produces(MediaType.APPLICATION_JSON)
    public Course createCourse(@FormParam("title") String title,@FormParam("code") String code) {
    Course course = new Course();
    course.setTitle(title);
    course.setCode(code);
    courseDao.save(course);
    return course;
    }

    Здесь я использовал аннотации FormParam для вставки значений формы в вызов метода. Вы заметите, что, используя соглашения REST, метод создания курса использует тип запроса PUT. Теперь давайте создадим страницу, чтобы ввести заголовок и код и создать курс. Обратите внимание, что наш метод возвращает созданный курс, чтобы мы могли вернуть курс обратно пользователю. Это, вероятно, не идеально, но подходит для демонстрации. Теперь давайте создадим новую HTML-страницу для ввода данных и вызова веб-службы для создания курса.

    <html>
    <head>
    <title>Insert title here</title>
    <script type="text/javascript"
    src="http://localhost:8080/restwebdemo/jquery-1.4.min.js">
    </script>
    </head>
    <body>
    <div id="message"
    style="display: none; background: #d0d0f0; padding: 12px">Message Div</div>
    <form action="rest/course/create" method="POST">

    <fieldset>
    <legend>Create Course</legend>
    <p>
    Title<br />
    <input id="title" /><br />
    </p>
    <p>
    Code<br />
    <input id="code" /><br />
    </p>
    <input type="submit" id="submit" />
    </fieldset>
    </form>
    </body>

    <script type="text/javascript">

    //jquery pieces
    $(document).ready(function() {

    //change the submit button behaviouus.
    $('#submit').click(function () {
    var title = $("input#title").val();
    var code = $("input#code").val();

    params = "title="+title+"&code="+code;
    //alert("posting form : "+data);
    $.ajax({
    type: "PUT",
    url: "rest/course/create",
    data: params,
    success: function(result) {
    showMessage("Created Course "+result.title+" with id "+result.id+" on "+result.createdOn);
    }
    });
    return false;
    });
    });

    function showMessage(msg) {
    $('#message').html(msg);
    $('#message').fadeIn('fast');
    $('#message').delay(3000).fadeOut('slow');
    }
    </script>
    </html>

    Это выглядит много кода, но не совсем. Мы импортируем jquery, чтобы помочь нам опубликовать нашу форму, и мы создаем нашу форму с двумя полями. Мы используем JQuery для добавления обработчика событий, поэтому, когда вы нажимаете кнопку отправить, он упаковывает форму, вызывает наш веб-сервис с запросом типа PUT, получает возвращенный объект как объект JSON и отображает сообщение, используя значения из нового Экземпляр получен с сервера. Чтобы убедиться, что ваш курс был создан, перейдите на первую страницу, и вы должны увидеть его в списке.

    Для этого поста, исходный код можно скачать с ( restwebdemo_pt2 ), просто распаковать его, использовать пакет mvn clean и развернуть войну на glassfish и использовать URL-адреса, упомянутые в статье.

     

С http://www.andygibson.net/blog/tutorial/simple-restful-services-in-glassfish-pt-2/