Статьи

Griffon Front-End, Grails Back-End: Отличный сквозной

Группы разработчиков для различных проектов Groovy отлично поработали, чтобы все их фреймворки хорошо работали вместе при создании и развертывании приложений. Если вы посетите раздел «Сеть» плагинов Griffon , вы можете заметить, что все эти плагины можно использовать для создания внешних интерфейсов Griffon для ваших веб-приложений, которые могут взаимодействовать с серверной частью Grails или любой другой серверной частью, которая поддерживает эти модули. технологии. Например, плагин Wsclient может создать сервис в Grails и экспортировать его через веб-сервисы. К этому сервису можно получить доступ из внешнего интерфейса Griffon. Благодаря отличной поддержке Grails для демонстрации поведения, подобного REST, и обширной архитектуре плагинов Griffon, Groovy становится внушительным комплексным решением для веб-приложений и веб-сервисов.

Чтобы настроить службу на стороне Grails, просто создайте новое приложение Grails:

grails create-app example

Затем перейдите в каталог приложения и установите плагин Grails Xfire:

grails install-plugin xfire

Плагин Wsclient, который добавляет клиент удаленного взаимодействия, способный взаимодействовать через SOAP, совместим с плагином Xfire 0.8.1.

Затем создайте MathService:

grails create-service MathService
grails-app/services/MathService.groovy

class MathService {
boolean transactional = false
static expose = ["xfire"]

double add(double arg0, double arg1){
println "add($arg0, $arg1)" // good old println() for quick debugging
return arg0 + arg1
}
}

Наконец, запустите приложение:

grails run-app

The next step is to build the Griffon application.  This one is named MathClient:

griffon create-app mathClient

And install the wsclient plugin:

griffon install-plugin wsclient

Modify the view script until it looks like this:

griffon-app/views/MathClientView.groovy

application(title: 'Wsclient Plugin Example',
pack: true,
locationByPlatform: true,
iconImage: imageIcon('/griffon-icon-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image,
imageIcon('/griffon-icon-16x16.png').image]) {
gridLayout(cols: 2, rows: 4)
label("Num1:")
textField(columns: 20, text: bind(target: model, targetProperty: "num1"))
label("Num2:")
textField(columns: 20, text: bind(target: model, targetProperty: "num2"))
label("Result:")
label(text: bind{model.result})
button("Calculate", enabled: bind{model.enabled}, actionPerformed: controller.calculate)
}

Add required properties to the model:

griffon-app/models/MathClientModel.groovy

import groovy.beans.Bindable

class MathClientModel {
@Bindable String num1
@Bindable String num2
@Bindable String result
@Bindable boolean enabled = true
}

Here is the controller code.  There is minimal error handling in place so if the user types something that is not a number, the client will break:

griffon-app/controllers/MathClientController.groovy

class MathClientController {
def model

def calculate = { evt = null ->
double a = model.num1.toDouble()
double b = model.num2.toDouble()
model.enabled = false
doOutside {
try {
def result = withWs(wsdl: "http://localhost:8080/exporter/services/math?wsdl") {
add(a, b)
}
doLater { model.result = result.toString() }
} finally {
model.enabled = true
}
}
}
}

Finally, start the application:

griffon run-app

When running, the wsclient plugin will add dynamic methods to controllers (the withWs() method at line 12).  A new wsclient proxy will be created every time you call those methods unless you define an id: attribute.  You can access the client via regular property access or using the id: again.  Dynamic methods will be added to controllers by default, but you can change this setting by adding a config flag in Application.groovy:

griffon.wsclient.injectInto = ["controller", "service"]

Other plugins like hessian, RMI, or XML-RPC follow the same principles in this example.  

Grails works well as a back-end because it’s good at outputting XML and easily ingesting it back.  Scott Davis’s Mastering Grails series gives a detailed demonstration for exposing REST-like behavior with Grails.  For enabling the usage of HTTPBuilder on a Griffon or Grails application, there are REST plugins available.

Here’s an example from HTTPBuilder’s Simplified GET Request using the REST plugin for Grails or Griffon:

withHttp(uri: "http://www.google.com") {
def html = get(path : '/search', query : [q:'Groovy'])
assert html.HEAD.size() == 1
assert html.BODY.size() == 1
}

The current HTTPBuilder is set as the closure’s delegate.  The same is true for the other dynamic methods

Here’s an example from AsyncHTTPBuilder:

import static groovyx.net.http.ContentType.HTML

withAsyncHttp(poolSize : 4, uri : "http://hc.apache.org", contentType : HTML) {
def result = get(path:'/') { resp, html ->
println ' got async response!'
return html
}
assert result instanceof java.util.concurrent.Future

while (! result.done) {
println 'waiting...'
Thread.sleep(2000)
}

/* The Future instance contains whatever is returned from the response
closure above; in this case the parsed HTML data: */
def html = result.get()
assert html instanceof groovy.util.slurpersupport.GPathResult
}

Once again, all dynamic methods will create a new http client when invoked unless you define an id: attribute.

class FooController {
def loginAction = { evt = null ->
withRest(id: "twitter", uri: "http://twitter.com/statuses/") {
auth.basic model.username, model.password
}
}

def queryAction = { evt = null ->
doOutside {
withRest(id: "twitter") {
def response = get(path: "followers.json")
// ...
}
/* alternatively
def response twitter.get(path: "followers.json")
*/
}
}
}

 

For the entire Mastering Grails series, you can follow this link.