Graeme Rocher 著 The Definitive Guide to Grails という本からブックマーク アプリを作成しています。このアプリでは、ブックマークを検索すると、del.icio.us でも検索され、両方の場所のブックマークが一覧表示されるサービスを作成しようとしています。私は Grails 1.3.9 を使用しており、Lib にあるファイルは Commons-codec-1.3、commons-httpclient-3.0.1、groovy-all-2.0.1 です。
ブックマーク ドメイン:
URL url
String title
String notes
ユーザー ドメイン:
static hasMany = [bookmarks:Bookmark]
String login
String password
(...)
ブックマークコントローラー - リスト:
def list = {
if(!params.max) {
params.max=10
}
def fromDelicious
try {
fromDelicious = deliciousService?.findRecent(session.user)
}
catch(Exception e) {
println e.message
e.printStackTrace(System.out)
}
[ bookmarkInstanceList: Bookmark.findAllByUser(session.user, params), deliciousList: fromDelicious ]
}
ブックマークコントローラー - 検索
def search = {
def b = criteria.list { ... }
def fromDelicious = null
try {
fromDelicious = deliciousService.findRecent(session.user)
}
catch(Exception e) {
log.error('Failed to invoke del.icio.us: ' + e.message, e)
}
render(view:'list',model:[bookmarkInstanceList:b.unique(),deliciousResults:fromDelicious])}
おいしいサービス:
static final API = "https://api.del.icio.us/v1"
static transactional = false
static final EXTRA_BOOKMARKS = {
xml -> def bookmarks = []
xml.post.each {
bookmarks << new Bookmark(title:"${p.@description}", url:new URL("${p.@href}"))
}
return bookmarks
}
List findRecent(User user) {
return withDelicious(name:"posts/recent",params:[count:5],user:user,EXTRACT_BOOKMARKS)
}
private withDelicious(args,callable) {
if(!args.user) throw new IllegalArgumentException("Property [user] is required and cannot be null")
def url = "${API}/${args.name}?"
args.params?.each {k,v->
url+="&$k=$v"
}
(...) callable( new XmlSlurper().parse(get.responseBodyAsStream) )
}
ビュー/ブックマーク/リスト
(...)
<g:if test="${deliciousList}">
<h2>Latest from <a href="http://del.icio.us/${session.user.login}" target="_blank">del.icio.us</a></h2>
<g:set var="edit" value="${false}" />
<g:render template="bookmark" var="bookmark" collection="${deliciousList}" />
</g:if>
<g:if test="${deliciousResults}">
<h2>Results from <a href="http://del.icio.us/${session.user.login}" target="_blank">del.icio.us</a></h2>
<g:render template="bookmark" var="bookmark" collection="${deliciousResults}" />
</g:if>
アプリを実行すると、コンソールに次のエラーが表示されます。
[http-8080-1] ERROR bookmarks.BookmarkController - Failed to invoke del.icio.us: No signature of method: bookmarks.DeliciousService.findRecent() is applicable for argument types: (bookmarks.User) values: [bookmarks.User : 1] Possible solutions: findResult(groovy.lang.Closure), findResult(java.lang.Object, groovy.lang.Closure)
デリシャスからパーツをリストしようとすると、それが表示されるはずの領域が空です (つまり、ビューの if が入っていないことを意味します)。また、findRecent() に送信する引数の何が問題なのかわかりません。