Introducing
Your new presentation assistant.
Refine, enhance, and tailor your content, source relevant images, and edit visuals quicker than ever before.
Trending searches
Addressable Resources
vs
URL based: "GETful"
Example: Google Chart API
http://chart.apis.google.com/chart?
plus lots of parameters
http://chart.apis.google.com/chart?&cht=bhs&chs=800x360&chd=t:10,15,25,40,65,100,-15,-30,-60,-90,5,10&chm=tInitial+publication,000000,0,0,12|tFavorable+mention+in+GroovyMag,000000,0,1,12|tJolt+award+nomination,000000,0,2,12|tWitty+repartee+on+Letterman,000000,0,3,12|tProduct+placement+in+Harry+Potter+movie,000000,0,4,12|tOprah%27s+Book+Club,000000,0,5,12|tDrunken+rant+on+Larry+King+Live,000000,0,6,12|tBug+found+in+book+source+code,000000,0,7,12|tInformercial+with+ShamWow+guy,000000,0,8,12|tScandalous+YouTube+video%28s%29,000000,0,9,12|tTearful+apology+on+The+View,000000,0,10,12|tO%27Reilly+%27Behind+the+Text%27+Special,000000,0,11,12&chds=-95,140&chtt=Anticipated+Impact+on+%22Making+Java+Groovy%22+Book+Sales&chco=0000ff|0000ff|0000ff|0000ff|0000ff|0000ff|ff0000|ff0000|ff0000|ff0000|0000ff|0000ff
Amazon Product API
Build URL with Groovy
def queryStrng = params.collect { k,v -> "$k=$v" }.join('&')
def url = "${baseUrl}?${queryString}"
Parse XML Results
def response = new XmlSlurper().parse(url)
def item = response.Items.Item
book.title = item.ItemAttributes.Title
Annotations for REST
+ WADL
Part of Java EE 6
"/product/$id"(controller:"product", parseRequest:true){
action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"]
}
import grails.converters.*
class ProductController {
def show = {
if(params.id && Product.exists(params.id)) {
def p = Product.findByName(params.id)
render p as XML
} else {
def all = Product.list()
render all as XML
}
}
}
import grails.converters.*
class BookController {
def books
def list = {
this.books = Book.list()
withFormat {
html bookList:books
js { render "alert('hello')" }
xml { render books as XML }
}
}
}
Example: ISBN Service
wsimport -keep -p mjg <wsdl_url>
Example: Potter's Potions, Ltd.
@WebService
public interface Wizard {
@WebMethod
@WebResult(name="potion")
Potion brewPotion(@WebParam(name="ingredients")
Ingredient[] elements);
@WebMethod
@WebResult(name="when")
Date sendOwl(@WebParam(name="message")
String message);
}
so much for interface / implemenation split
HTTPBuilder
GroovyWS
@WebService(endpointInterface="Wizard")
class Granger implements Wizard {
Potion brewPotion(Ingredient[] elements) {
return new Potion(name:'polyjuice',
effect:'change appearance');
}
Date sendOwl(String message) {
return new Date()
}
}
@WebService(endpointInterface="Wizard")
class HogwartsWizard implements Wizard {
@Delegate Wizard wizard
}
Working from SIB puts SIB class name in WSDL for service and port
Wizard wiz = new HogwartsWizard(
wizard:new Granger())
Endpoint.publish('http://.../potions', wiz)
println 'Ready to receive requests...'
JAX-RS (JSR 311)
"Jersey"
Restlets
Grails
@WebService(endpointInterface="Wizard")
public class Weasley implements Wizard {
public Potion brewPotion(Ingredient[] elements) {
Potion p = new Potion();
p.setName("veritiserum");
p.setEffect("makes you tell the truth");
return p;
}
public Date sendOwl(String message) {
return new Date();
}
}
wsgen works from SIBs
(Service Implementation Beans)
def url = 'http://chart.apis.google.com/chart?'
def data = ['Initial publication':10,'Favorable mention in GroovyMag':15,
'Jolt award nomination':25,'Witty repartee on Letterman':40,
'Product placement in Harry Potter movie':65,"Oprah's Book Club":100,
'Drunken rant on Larry King Live':-15,'Bug found in book source code':-30,
'Informercial with ShamWow guy':-60,'Scandalous YouTube video(s)':-90,
'Tearful apology on The View':5,"O'Reilly 'Behind the Text' Special":10
]
// For bar chart, format is;
// label,label_color,data_set,point_index,label_size
// Would use a collect here instead, but need an index
def transformed = []
data.keySet().eachWithIndex { val, i ->
transformed << "t${URLEncoder.encode(val,'UTF-8')},000000,0,$i,12"
}
// Blue for positive, red for negative
def colors = data.values().collect() {
(it < 0 ? 'ff0000' : '0000ff')
}.join('|')
def title = 'Anticipated Impact on "Making Java Groovy" Book Sales'
def map = [
'cht' : 'bhs',
'chs' : '800x360',
'chd' : 't:'+ data.values().join(','),
'chm' : transformed.join('|'),
'chds': '-95,140',
'chtt': URLEncoder.encode(title,'UTF-8'),
'chco': colors
]
map.each { key, value ->
url += "&${key}=${value}"
}
println url
Wizard w = new HogwartsWizardService().getHogwartsWizardPort()
def ingredients = []
ingredients << new Ingredient(name:'Sopophorous bean',amount:1)
Potion p = w.brewPotion(ingredients)
println "$p.name: $p.effect"
Looks almost identical
but Java Potions and Ingredients
POJO, not POGO
Use @WebMethod
or all public methods exposed
including invokeMethod(), etc
@WebService
interface Wizard {
@WebMethod
@WebResult(name="potion")
Potion brewPotion(@WebParam(name="ingredients")
Ingredient[] elements);
@WebMethod
@WebResult(name="when")
Date sendOwl(@WebParam(name="message")
String message);
}
JAX-WS --> JAXB
--> POGO properties
--> getMetaClass()
--> problems
generates WSDL
(and artifacts)
from bytecodes
Use field access rather than properties
@XmlAccessorType(XmlAccessType.FIELD)
class Potion {
String name
String effect
}
Special @XMLAccessor annotation
WSDL --> Java
generates Java stubs from WSDL
Holy code generation, Batman
http://webservices.daehosting.com/services/isbnservice.wso?WSDL
Java --> WSDL
def getGame(away,home,year) {
def box = new XmlParser.parse(...)
def awayName = box.@away_fname
...
// add extracted data to a POGO
}
wsimport <options> <wsdl_loc>
ISBNServiceSOAPType service =
new ISBNService().getISBNServiceSOAP()
boolean ok = service.isValidISBN10("0978739299")
Invoke with Groovy (or Java)
Generate XML with MarkupBuilder
JAX-WS 2.0, including JAXB 2.0
JAX-WS 2.1+ available from Metro
Parse or Slurp XML
annotation processing tool
Ken Kousen
works with Java source only
Kousen IT, Inc.
ken.kousen@kousenit.com
http://www.kousenit.com
Online XML game data
http://gd2.mlb.com/components/game/mlb
boxscores for all games on year, month, day
Data in XML format
blog: http://kousenit.wordpress.com
WSDL
twitter: @kenkousen
O'Reilly, 2010 (?)
ISBN 0978739299
Top Down
Bottom Up
Intercept SOAP Messages
builder.games {
games.each { g ->
game(
outcome:"$g.away $g.aScore, ...",
lat:g.stadium.latitude,
lng:g.stadium.longitude
)
}
}
Process using SOAP with Attachments API for Java (SAAJ)
thyme
parsley
rosemary
Ugly, awkward in Java
Simple, elegant in Groovy
(Do-it-yourself AOP)
Logging, security, encryption, routing, etc.
Publish and access web services
Built on Apache HttpClient library
Uses Apache CXF
Automatic parsing based on content type
Uses Groovy builder syntax