25 июля 2012 г.

Создание и работа с RESTful web service в Groovy/Grails

Программисты всегда хотели упростить себе жизнь. Одна парадигма сменялась другой, появлялись новые языки, новые подходы. В мире веб-разработки произошли большие изменения - появились такие фреймворки, как Ruby on Rails, Django. И если еще можно вести долгие споры что же использовать для создания сайтов (PHP, RoR, Lift), то для веб сервисов в enterprise традиционно используется Java. Оглянитесь, не смотря на возможность реализации веб сервисов на руби или питоне или любом другом вашем любимом языке, enterprise-мир эту возможность не использует! В первую очередь это связано с проблемой интеграции данных сервисов в существующее java-окружение. К счастью существуют языки на 100% совместимые с java, которые могут помочь нам, простым скромым программистам, уменьшить рутину и оставить для разработки только самые интересные части системы. Одним из этих языков является Groovy. Сегодня я хочу рассказать как с помощью Groovy и Grails написать простенький веб-сервис. Кто знает, возможно вам удастся убедить вашего начальника, что время быстрой разарботки уже пришло?


В мире веб-разработки традиционно, при создании первых приложений, пишутся телефонные справочники. Последуем традиции и напишем веб сервис для этого справочника. Не будем усложнять с доменным уровнем: пусть у нас будет только один класс - Person. Допустим такой:
class Person {
  String firstname
  String lastname
  Integer phone
  String email

  static constraints = {
    firstname blank:false
    lastname blank:false
    phone size:10
    email email:true
  }
}
RESTful web service должен оперировать стандартными web-методами: GET, POST, PUT и DELETE. По запросу GET мы должны предоставить пользователю информацию о человеке из адресной книги, по POST - сохранить контакт, по PUT - обновить и по DELETE - удалить. Опишем эти принципы в маппинге адресов нашего приложения - модифицируем класс UrlMappings, чтобы он стал таким:
class UrlMappings {
    static mappings = {
        "/person"(controller:"person") {
            action = [GET:"show", POST:"save", PUT:"update", DELETE:"remove"]
        }
    }
}
Осталось совсем недолго! Теперь создадим контроллер, который собственно и будет нашим веб сервисом. Следуя традициям Grails, назовем его в честь доменного класса - PersonController:
package phonebookws

import grails.converters.JSON
import javax.validation.ValidationException

class PersonController {

 def show() {
  if(params.id && Person.exists(params.id)) {
   render Person.get(params.id) as JSON
  } else {
   render Person.list() as JSON
  }
 }
 
 def save() {
  def person = new Person(params)
  if(!person.validate())
   throw new ValidationException("Person data is not valid", person.errors)
  
  person.save()
  render person as JSON
 }
 
 def update() {
  def userPerson = new Person(params)

  if(!userPerson.validate())
   throw new ValidationException("Person data is not valid", userPerson.errors)
  
  if(userPerson.id && Person.exists(userPerson.id)) { 
   def dbPerson = Person.get(userPerson.id)
  
   if (!userPerson.firstname.empty)
       dbPerson.firstname = userPerson.firstname;
   if (!userPerson.lastname.empty)
    dbPerson.lastname = userPerson.lastname;
   if (!userPerson.phone != 0)
    dbPerson.phone = userPerson.phone;
   if (!userPerson.email.empty)
    dbPerson.email = userPerson.email;
   dbPerson.save()
  }
 }
 
 def remove() {
  if(params.id && Person.exitsts(params.id)) {
   def person = Person.get(params.id)
   person.delete()
  }
 }
}

Веб сервис готов! Конечно, он получился не чудом инженерной мысли и далеко не самым элегентным, но он работает, в чем вы можете убедиться написав для него клиента. Например, так:
@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.2' )
import groovyx.net.http.*
 
def http = new HTTPBuilder( 'http://localhost:8080/PhoneBookWS/' )

pbody = [
 lastname:'Marley',
 firstname:'Bob',
 email: 'bob@marley.com',
 phone: 1234567890
]

http.post (path: 'person', body: pbody) { resp ->
    println "New record is created."
}

http.get( path: 'person', query: [id:1] ) { resp, json ->
    println json 
}
Как не трудно догадаться, в этом примере мы создаем запись в адресной книге, а затем выводим её.

Комментариев нет:

Отправить комментарий

Примечание. Отправлять комментарии могут только участники этого блога.