Easy REST APIs with Jersey and RestyGWT

David Chandler
David ChandlerDeveloper Advocate
Easy REST APIs with
Jersey and RestyGWT
David Chandler
turbomanage.wordpress.com
why RestyGWT?
Ease of GWT-RPC
Power of Command pattern
Less boilerplate
Easier testing
get started
pom.xml
<dependency>

<groupId>org.fusesource.restygwt</groupId>

<artifactId>restygwt</artifactId>

<version>1.4</version>

</dependency>

<dependency>

<groupId>javax.ws.rs</groupId>

<artifactId>jsr311-api</artifactId>

<version>1.1.1</version>

</dependency>

*.gwt.xml
<inherits name="org.fusesource.restygwt.RestyGWT"/>
https://resty-gwt.github.io/
map JSON
public class YqlResponse {

public YqlQuery query;



public static class YqlQuery {

public YqlResults results;



public static class YqlResults {

public List<Quote> quote;

}

}

}

no annotations needed
create a service API
@Path("http://query.yahooapis.com/v1/public")

public interface QuoteService extends RestService {

@GET

@Path("yql")

public void get(

@QueryParam("q") String query,

@QueryParam("env") String env,

@QueryParam("format") String format,

MethodCallback<YqlResponse> callback);

}

invoke the service
private static final QuoteService svc = GWT.create(QuoteService.class);



@Override

public void load(LoaderDemo.QuoteRequest input, final Callback<ListLoadResult<Quote>,
Throwable> callback) {

svc.get(input.getYql(), ENV, FORMAT, new MethodCallback<YqlResponse>() {

@Override

public void onFailure(Method method, Throwable throwable) {

Info.display("QuoteProxy", "failure");

callback.onFailure(throwable);

}



@Override

public void onSuccess(Method method, YqlResponse yqlResponse) {

List<Quote> quotes = yqlResponse.query.results.quote;

Info.display("QuoteProxy", "success");

callback.onSuccess(new ListLoadResultBean<Quote>(quotes));

}

});

}

simple CRUD API
public interface RestApi<T> extends RestService {



@GET

@Path("get")

public void get(@QueryParam("id")Long id, MethodCallback<T> callback);



@GET

@Path("all")

public void listAll(MethodCallback<ListResponse<T>> callback);



@POST

@Path("save")

public void save(T obj, MethodCallback<T> callback);



@POST

@Path("saveMany")

public void saveMany(List<T> obj, MethodCallback<Integer> callback);



@POST

@Path("delete")

public void delete(Long id, MethodCallback<Integer> callback);



}

not much here!
minimal boilerplate
@Path("/api/note")

public interface NoteItemRestService extends RestApi<Note> { }



private static final NoteItemRestService service = GWT.create(NoteItemRestService.class);



public void addNote(Display display, long listId, Note item)

{

NoteList noteList = App.getNoteListService().getNoteList(listId);

// All are 0-based for consistency with GWT constants

item.listId = listId;

service.save(item, new AppCallback<Note>(display) {

@Override

public void handleSuccess(Note result) {

App.getAppModel().getAllNotes().add(0, result);

App.getEventBus().fireEvent(new ShowMessageEvent("Note saved."));

App.getEventBus().fireEvent(new
NotesLoadedEvent(App.getAppModel().getAllNotes()));

App.getEventBus().fireEvent(new NoteAddedEvent(result));

}

});

}

public class ProjectEntryPoint implements EntryPoint {



private static DispatcherFactory dispatcherFactory = new DispatcherFactory();

private static FilterawareDispatcher dispatcher =
dispatcherFactory.cachingDispatcher();



@Override

public void onModuleLoad() {

// Configure RestyGWT

dispatcher.addFilter(new CORSFilter());

Defaults.setDispatcher(dispatcher);



LoaderDemo loaderDemo = new LoaderDemo();

RootPanel.get().add(loaderDemo);

}



}
ListAllNotesAction, ListAllNotesResult,

AddNoteAction, AddNoteResult, …
Command pattern
server side
@Path("api/note")

public class NoteDao extends RestServiceDao<Note>

{


private static final Logger LOG = Logger.getLogger(NoteDao.class.getName());



@Override

@Path("all")

@GET

public ListWrapper<Note> findAll() {

User user = AuthFilter.getUser();

List<Note> notes = this.listByOwner(user);

return new ListWrapper<Note>(notes);

}
. . .
}
Objectify + Jersey
@Produces(MediaType.APPLICATION_JSON)

public class RestServiceDao<T extends Owned> extends ObjectifyDao<T>

{



public T getForOwner() {

User user = AuthFilter.getUser();

T obj = null;

try {

obj = this.getByOwner(user);

return obj;

} catch (TooManyResultsException e) {

throw new WebApplicationException(e);

}

}



public ListWrapper<T> findAll() {

User user = AuthFilter.getUser();

List<T> userAll = this.listByOwner(user);

return new ListWrapper<T>(userAll);

}
. . .
}

getting Jersey
pom.xml
<dependency>

<groupId>org.glassfish.jersey.containers</groupId>

<!-- if your container implements Servlet API older than 3.0, 

use "jersey-container-servlet-core" -->

<artifactId>jersey-container-servlet-core</artifactId>

<version>2.7</version>

</dependency>

<!-- workaround for https://java.net/jira/browse/JERSEY-2459 -->

<dependency>

<groupId>org.glassfish.hk2</groupId>

<artifactId>hk2-api</artifactId>

<version>2.3.0-b09</version>

</dependency>

<dependency>

<groupId>com.fasterxml.jackson.jaxrs</groupId>

<artifactId>jackson-jaxrs-json-provider</artifactId>

<version>2.3.2</version>

</dependency>

Jersey config
web.xml
<servlet>

<servlet-name>jerseyServlet</servlet-name>

<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

<init-param>

<param-name>jersey.config.server.provider.packages</param-name>

<param-value>com.example.listmaker.server</param-value>

</init-param>

<init-param>

<!-- speed up initial Jersey loading by deactivating WADL -->

<param-name>jersey.config.server.wadl.disableWadl</param-name>

<param-value>true</param-value>

</init-param>

<init-param>

<param-name>jersey.config.server.provider.classnames</param-name>

<param-value>org.glassfish.jersey.filter.LoggingFilter</param-value>

</init-param>

<load-on-startup>1</load-on-startup>

</servlet>



<servlet-mapping>

<servlet-name>jerseyServlet</servlet-name>

<url-pattern>/listmaker/*</url-pattern>

</servlet-mapping>

what about auth?
AuthFilter.java
// if an API call, return JSON response

if (path.startsWith("/listmaker/api")) {

((HttpServletResponse) resp).setStatus(401);

resp.setContentType(MediaType.TEXT_PLAIN);

resp.getWriter().write("User must log in");

} else {

// otherwise redirect

httpRes.sendRedirect(LOGIN_FORM);

}
<filter>

<filter-name>AuthFilter</filter-name>

<filter-class>com.turbomanage.gwt.server.servlet.AuthFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>AuthFilter</filter-name>

<url-pattern>/listmaker/*</url-pattern>

</filter-mapping>

exception handling
@Override

public void onFailure(Method method, Throwable throwable) {

String url = method.builder.getUrl();



App.getLogger().log(Level.SEVERE, "Error calling service " + url, throwable);

try {

// Decode the exception

if (throwable instanceof FailedStatusCodeException) {

FailedStatusCodeException sce = (FailedStatusCodeException) throwable;

App.getLogger().log(Level.SEVERE, "Service returned " + sce.getStatusCode() +
sce.getMessage());

if (401 == sce.getStatusCode()) {

Window.Location.replace(LOGIN_FORM);

} else if (500 == sce.getStatusCode()) {

if ("UserNotRegisteredException".equals(sce.getMessage())) {

Window.Location.replace(SIGNUP_URL);

}

}

}

handleFailure(throwable);

} finally {

reset(null);

}

}

application error handling
service.save(item, new AppCallback<Note>(display) {

@Override

public void handleSuccess(Note result) {

. . .
}

});
public abstract class AppCallback<R> implements MethodCallback<R> {



private final Display display;



public AppCallback() {

this.display = null;

}



public AppCallback(Display display) {

this.display = display;

display.startProcessing();

}
. . .
}
finer points
Text, JSON, XML via direct API — res.get()…
CachingRetryingDispatcher
ModelChangeEvent
Objects with final fields (@JsonCreator)
Polymorphism (@JsonSubTypes)
same obj on client / server?
older versions of RestyGWT used Jackson 1.7
RestyGWT 2.0 uses Jackson 2.3
so you can now use the same annotations on client
and server
and therefore the same POJOs (yeah)!
use @JsonIgnore for server-only fields (like Ref)
Please rate this session at
gwtcreate.com/agenda
src
github.com/turbomanage/listmaker
David Chandler
turbomanage.wordpress.com
resty-gwt.github.io
1 of 19

Recommended

Guice2.0 by
Guice2.0Guice2.0
Guice2.0Masaaki Yonebayashi
1.4K views73 slides
Why Kotlin - Apalon Kotlin Sprint Part 1 by
Why Kotlin - Apalon Kotlin Sprint Part 1Why Kotlin - Apalon Kotlin Sprint Part 1
Why Kotlin - Apalon Kotlin Sprint Part 1Kirill Rozov
483 views30 slides
Android TDD by
Android TDDAndroid TDD
Android TDDGodfrey Nolan
2.2K views58 slides
Retrofit Technology Overview by Cumulations Technologies by
Retrofit Technology Overview by Cumulations TechnologiesRetrofit Technology Overview by Cumulations Technologies
Retrofit Technology Overview by Cumulations TechnologiesCumulations Technologies
551 views25 slides
Android Design Patterns by
Android Design PatternsAndroid Design Patterns
Android Design PatternsGodfrey Nolan
4K views49 slides
Тестирование на Android с Dagger 2 by
Тестирование на Android с Dagger 2Тестирование на Android с Dagger 2
Тестирование на Android с Dagger 2Kirill Rozov
283 views31 slides

More Related Content

What's hot

Making the most of your gradle build - Greach 2017 by
Making the most of your gradle build - Greach 2017Making the most of your gradle build - Greach 2017
Making the most of your gradle build - Greach 2017Andres Almiray
992 views47 slides
Testing Java Code Effectively by
Testing Java Code EffectivelyTesting Java Code Effectively
Testing Java Code EffectivelyAndres Almiray
1.6K views46 slides
Testing Android apps based on Dagger and RxJava by
Testing Android apps based on Dagger and RxJavaTesting Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJavaFabio Collini
1.5K views79 slides
Finding Clojure by
Finding ClojureFinding Clojure
Finding ClojureMatthew McCullough
1.1K views22 slides
Unit testing with mock libs by
Unit testing with mock libsUnit testing with mock libs
Unit testing with mock libsValentin Kolesnikov
691 views12 slides
XTW_Import by
XTW_ImportXTW_Import
XTW_ImportLuther Quinn
444 views12 slides

What's hot(20)

Making the most of your gradle build - Greach 2017 by Andres Almiray
Making the most of your gradle build - Greach 2017Making the most of your gradle build - Greach 2017
Making the most of your gradle build - Greach 2017
Andres Almiray992 views
Testing Java Code Effectively by Andres Almiray
Testing Java Code EffectivelyTesting Java Code Effectively
Testing Java Code Effectively
Andres Almiray1.6K views
Testing Android apps based on Dagger and RxJava by Fabio Collini
Testing Android apps based on Dagger and RxJavaTesting Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJava
Fabio Collini1.5K views
JJUG CCC 2011 Spring by Kiyotaka Oku
JJUG CCC 2011 SpringJJUG CCC 2011 Spring
JJUG CCC 2011 Spring
Kiyotaka Oku1.7K views
Architecture Components by Sang Eel Kim
Architecture ComponentsArchitecture Components
Architecture Components
Sang Eel Kim1K views
The Ring programming language version 1.9 book - Part 11 of 210 by Mahmoud Samir Fayed
The Ring programming language version 1.9 book - Part 11 of 210The Ring programming language version 1.9 book - Part 11 of 210
The Ring programming language version 1.9 book - Part 11 of 210
The uniform interface is 42 by Yevhen Bobrov
The uniform interface is 42The uniform interface is 42
The uniform interface is 42
Yevhen Bobrov345 views
What's new in Android O by Kirill Rozov
What's new in Android OWhat's new in Android O
What's new in Android O
Kirill Rozov1.9K views
Amazon Cognito使って認証したい?それならSpring Security使いましょう! by Ryosuke Uchitate
Amazon Cognito使って認証したい?それならSpring Security使いましょう!Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Amazon Cognito使って認証したい?それならSpring Security使いましょう!
Ryosuke Uchitate17K views
The Ring programming language version 1.5.3 book - Part 26 of 184 by Mahmoud Samir Fayed
The Ring programming language version 1.5.3 book - Part 26 of 184The Ring programming language version 1.5.3 book - Part 26 of 184
The Ring programming language version 1.5.3 book - Part 26 of 184
Spring & Hibernate by Jiayun Zhou
Spring & HibernateSpring & Hibernate
Spring & Hibernate
Jiayun Zhou245 views
Intro to Retrofit 2 and RxJava2 by Fabio Collini
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2
Fabio Collini3.1K views
T.Y.B.S.CS Advance Java Practicals Sem 5 Mumbai University by Niraj Bharambe
T.Y.B.S.CS Advance Java Practicals Sem 5 Mumbai UniversityT.Y.B.S.CS Advance Java Practicals Sem 5 Mumbai University
T.Y.B.S.CS Advance Java Practicals Sem 5 Mumbai University
Niraj Bharambe435 views

Viewers also liked

GWT integration with Vaadin by
GWT integration with VaadinGWT integration with Vaadin
GWT integration with VaadinPeter Lehto
1.4K views144 slides
RestFull Webservices with JAX-RS by
RestFull Webservices with JAX-RSRestFull Webservices with JAX-RS
RestFull Webservices with JAX-RSNeil Ghosh
3.4K views31 slides
JSR 339 - Java API for RESTful Web Services by
JSR 339 - Java API for RESTful Web ServicesJSR 339 - Java API for RESTful Web Services
JSR 339 - Java API for RESTful Web ServicesDaniel Cunha
1.3K views166 slides
Real world RESTful service development problems and solutions by
Real world RESTful service development problems and solutionsReal world RESTful service development problems and solutions
Real world RESTful service development problems and solutionsBhakti Mehta
2K views75 slides
Artsofte облегченная веб шина данных для организации дистанционных каналов пр... by
Artsofte облегченная веб шина данных для организации дистанционных каналов пр...Artsofte облегченная веб шина данных для организации дистанционных каналов пр...
Artsofte облегченная веб шина данных для организации дистанционных каналов пр...Artsofte IT company
1.4K views38 slides
figo at FinTech Startups MeetUp in Hamburg by
figo at FinTech Startups MeetUp in Hamburgfigo at FinTech Startups MeetUp in Hamburg
figo at FinTech Startups MeetUp in HamburgLars Markull
1.8K views18 slides

Viewers also liked(16)

GWT integration with Vaadin by Peter Lehto
GWT integration with VaadinGWT integration with Vaadin
GWT integration with Vaadin
Peter Lehto1.4K views
RestFull Webservices with JAX-RS by Neil Ghosh
RestFull Webservices with JAX-RSRestFull Webservices with JAX-RS
RestFull Webservices with JAX-RS
Neil Ghosh3.4K views
JSR 339 - Java API for RESTful Web Services by Daniel Cunha
JSR 339 - Java API for RESTful Web ServicesJSR 339 - Java API for RESTful Web Services
JSR 339 - Java API for RESTful Web Services
Daniel Cunha1.3K views
Real world RESTful service development problems and solutions by Bhakti Mehta
Real world RESTful service development problems and solutionsReal world RESTful service development problems and solutions
Real world RESTful service development problems and solutions
Bhakti Mehta2K views
Artsofte облегченная веб шина данных для организации дистанционных каналов пр... by Artsofte IT company
Artsofte облегченная веб шина данных для организации дистанционных каналов пр...Artsofte облегченная веб шина данных для организации дистанционных каналов пр...
Artsofte облегченная веб шина данных для организации дистанционных каналов пр...
Artsofte IT company1.4K views
figo at FinTech Startups MeetUp in Hamburg by Lars Markull
figo at FinTech Startups MeetUp in Hamburgfigo at FinTech Startups MeetUp in Hamburg
figo at FinTech Startups MeetUp in Hamburg
Lars Markull1.8K views
JAX-RS 2.0: RESTful Web Services by Arun Gupta
JAX-RS 2.0: RESTful Web ServicesJAX-RS 2.0: RESTful Web Services
JAX-RS 2.0: RESTful Web Services
Arun Gupta5.5K views
Управление идентификационными данными и доступом by КРОК
Управление идентификационными данными и доступомУправление идентификационными данными и доступом
Управление идентификационными данными и доступом
КРОК419 views
Необходимые условия качества данных: MDM, Шина, Хранилище данных by КРОК
Необходимые условия качества данных: MDM, Шина, Хранилище данныхНеобходимые условия качества данных: MDM, Шина, Хранилище данных
Необходимые условия качества данных: MDM, Шина, Хранилище данных
КРОК843 views
Интеграция данных и приложений: основа для единой ИТ-инфраструктуры by КРОК
Интеграция данных и приложений: основа для единой ИТ-инфраструктурыИнтеграция данных и приложений: основа для единой ИТ-инфраструктуры
Интеграция данных и приложений: основа для единой ИТ-инфраструктуры
КРОК1K views
Open Source Integration with WSO2 Enterprise Service Bus by sumedha.r
Open Source Integration  with  WSO2 Enterprise Service BusOpen Source Integration  with  WSO2 Enterprise Service Bus
Open Source Integration with WSO2 Enterprise Service Bus
sumedha.r3K views
Oracle Service Bus vs. Oracle Enterprise Service Bus vs. BPEL by Guido Schmutz
Oracle Service Bus vs. Oracle Enterprise Service Bus vs. BPELOracle Service Bus vs. Oracle Enterprise Service Bus vs. BPEL
Oracle Service Bus vs. Oracle Enterprise Service Bus vs. BPEL
Guido Schmutz23.8K views
Enterprise service bus(esb) by prksh89
Enterprise service bus(esb)Enterprise service bus(esb)
Enterprise service bus(esb)
prksh8915K views
Produktivität - 5 Tricks, um in weniger Zeit mehr zu erledigen by FastBill
Produktivität - 5 Tricks, um in weniger Zeit mehr zu erledigenProduktivität - 5 Tricks, um in weniger Zeit mehr zu erledigen
Produktivität - 5 Tricks, um in weniger Zeit mehr zu erledigen
FastBill19.1K views
Microservices = Death of the Enterprise Service Bus (ESB)? by Kai Wähner
Microservices = Death of the Enterprise Service Bus (ESB)?Microservices = Death of the Enterprise Service Bus (ESB)?
Microservices = Death of the Enterprise Service Bus (ESB)?
Kai Wähner35.5K views
Become a Presentation Hero: 21 tips by Tom De Ruyck
Become a Presentation Hero: 21 tipsBecome a Presentation Hero: 21 tips
Become a Presentation Hero: 21 tips
Tom De Ruyck39.2K views

Similar to Easy REST APIs with Jersey and RestyGWT

比XML更好用的Java Annotation by
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotationjavatwo2011
1K views45 slides
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson by
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy ClarksonMulti Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy ClarksonJoshua Long
1.8K views62 slides
Taming Core Data by Arek Holko, Macoscope by
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeMacoscope
498 views103 slides
Brief Intro To Jax Rs by
Brief Intro To Jax RsBrief Intro To Jax Rs
Brief Intro To Jax RsEduardo Pelegri-Llopart
299 views6 slides
Spring into rails by
Spring into railsSpring into rails
Spring into railsHiro Asari
1K views40 slides
Java Libraries You Can’t Afford to Miss by
Java Libraries You Can’t Afford to Miss Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to Miss Andres Almiray
3K views64 slides

Similar to Easy REST APIs with Jersey and RestyGWT(20)

比XML更好用的Java Annotation by javatwo2011
比XML更好用的Java Annotation比XML更好用的Java Annotation
比XML更好用的Java Annotation
javatwo20111K views
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson by Joshua Long
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy ClarksonMulti Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Joshua Long1.8K views
Taming Core Data by Arek Holko, Macoscope by Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
Macoscope498 views
Spring into rails by Hiro Asari
Spring into railsSpring into rails
Spring into rails
Hiro Asari1K views
Java Libraries You Can’t Afford to Miss by Andres Almiray
Java Libraries You Can’t Afford to Miss Java Libraries You Can’t Afford to Miss
Java Libraries You Can’t Afford to Miss
Andres Almiray3K views
ASP.NET Web API by habib_786
ASP.NET Web APIASP.NET Web API
ASP.NET Web API
habib_7867.1K views
Native REST Web Services with Oracle 11g by Marcelo Ochoa
Native REST Web Services with Oracle 11gNative REST Web Services with Oracle 11g
Native REST Web Services with Oracle 11g
Marcelo Ochoa3.4K views
OSGi ecosystems compared on Apache Karaf - Christian Schneider by mfrancis
OSGi ecosystems compared on Apache Karaf - Christian SchneiderOSGi ecosystems compared on Apache Karaf - Christian Schneider
OSGi ecosystems compared on Apache Karaf - Christian Schneider
mfrancis2.4K views
Overview of Android Infrastructure by Alexey Buzdin
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
Alexey Buzdin5.5K views
Overview of Android Infrastructure by C.T.Co
Overview of Android InfrastructureOverview of Android Infrastructure
Overview of Android Infrastructure
C.T.Co424 views
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge by mfrancis
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R AugeHTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
HTTP Whiteboard - OSGI Compendium 6.0 - How web apps should have been! - R Auge
mfrancis1.9K views
Overview of RESTful web services by nbuddharaju
Overview of RESTful web servicesOverview of RESTful web services
Overview of RESTful web services
nbuddharaju4.2K views
Cloud nativeworkshop by Emily Jiang
Cloud nativeworkshopCloud nativeworkshop
Cloud nativeworkshop
Emily Jiang141 views
Testing in android by jtrindade
Testing in androidTesting in android
Testing in android
jtrindade301 views
May 2010 - RestEasy by JBug Italy
May 2010 - RestEasyMay 2010 - RestEasy
May 2010 - RestEasy
JBug Italy1.3K views

More from David Chandler

Taking Your GWT App to Tablets with GXT 4.0 by
Taking Your GWT App to Tablets with GXT 4.0Taking Your GWT App to Tablets with GXT 4.0
Taking Your GWT App to Tablets with GXT 4.0David Chandler
1.8K views46 slides
StORM: a lightweight ORM for Android SQLite by
StORM: a lightweight ORM for Android SQLiteStORM: a lightweight ORM for Android SQLite
StORM: a lightweight ORM for Android SQLiteDavid Chandler
888 views27 slides
Cómo trabajan los Googlers by
Cómo trabajan los GooglersCómo trabajan los Googlers
Cómo trabajan los GooglersDavid Chandler
932 views23 slides
Life of an engineer by
Life of an engineerLife of an engineer
Life of an engineerDavid Chandler
3.9K views13 slides
StORM preview by
StORM previewStORM preview
StORM previewDavid Chandler
622 views24 slides
Google App Engine Update 2012 by
Google App Engine Update 2012Google App Engine Update 2012
Google App Engine Update 2012David Chandler
1.8K views50 slides

More from David Chandler(14)

Taking Your GWT App to Tablets with GXT 4.0 by David Chandler
Taking Your GWT App to Tablets with GXT 4.0Taking Your GWT App to Tablets with GXT 4.0
Taking Your GWT App to Tablets with GXT 4.0
David Chandler1.8K views
StORM: a lightweight ORM for Android SQLite by David Chandler
StORM: a lightweight ORM for Android SQLiteStORM: a lightweight ORM for Android SQLite
StORM: a lightweight ORM for Android SQLite
David Chandler888 views
Google App Engine Update 2012 by David Chandler
Google App Engine Update 2012Google App Engine Update 2012
Google App Engine Update 2012
David Chandler1.8K views
Scalable Apps with Google App Engine by David Chandler
Scalable Apps with Google App EngineScalable Apps with Google App Engine
Scalable Apps with Google App Engine
David Chandler4.1K views
Develop and Deploy Scalable Apps with Google App Engine by David Chandler
Develop and Deploy Scalable Apps with Google App EngineDevelop and Deploy Scalable Apps with Google App Engine
Develop and Deploy Scalable Apps with Google App Engine
David Chandler3.1K views
The 90-Day Startup with Google AppEngine for Java by David Chandler
The 90-Day Startup with Google AppEngine for JavaThe 90-Day Startup with Google AppEngine for Java
The 90-Day Startup with Google AppEngine for Java
David Chandler1.4K views
Securing JSF Applications Against the OWASP Top Ten by David Chandler
Securing JSF Applications Against the OWASP Top TenSecuring JSF Applications Against the OWASP Top Ten
Securing JSF Applications Against the OWASP Top Ten
David Chandler2.2K views

Recently uploaded

Automated Testing of Microsoft Power BI Reports by
Automated Testing of Microsoft Power BI ReportsAutomated Testing of Microsoft Power BI Reports
Automated Testing of Microsoft Power BI ReportsRTTS
10 views20 slides
EV Charging App Case by
EV Charging App Case EV Charging App Case
EV Charging App Case iCoderz Solutions
9 views1 slide
Navigating container technology for enhanced security by Niklas Saari by
Navigating container technology for enhanced security by Niklas SaariNavigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas SaariMetosin Oy
15 views34 slides
The Path to DevOps by
The Path to DevOpsThe Path to DevOps
The Path to DevOpsJohn Valentino
5 views6 slides
FOSSLight Community Day 2023-11-30 by
FOSSLight Community Day 2023-11-30FOSSLight Community Day 2023-11-30
FOSSLight Community Day 2023-11-30Shane Coughlan
7 views18 slides
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium... by
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...Lisi Hocke
35 views124 slides

Recently uploaded(20)

Automated Testing of Microsoft Power BI Reports by RTTS
Automated Testing of Microsoft Power BI ReportsAutomated Testing of Microsoft Power BI Reports
Automated Testing of Microsoft Power BI Reports
RTTS10 views
Navigating container technology for enhanced security by Niklas Saari by Metosin Oy
Navigating container technology for enhanced security by Niklas SaariNavigating container technology for enhanced security by Niklas Saari
Navigating container technology for enhanced security by Niklas Saari
Metosin Oy15 views
FOSSLight Community Day 2023-11-30 by Shane Coughlan
FOSSLight Community Day 2023-11-30FOSSLight Community Day 2023-11-30
FOSSLight Community Day 2023-11-30
Shane Coughlan7 views
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium... by Lisi Hocke
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...
Team Transformation Tactics for Holistic Testing and Quality (Japan Symposium...
Lisi Hocke35 views
Bootstrapping vs Venture Capital.pptx by Zeljko Svedic
Bootstrapping vs Venture Capital.pptxBootstrapping vs Venture Capital.pptx
Bootstrapping vs Venture Capital.pptx
Zeljko Svedic15 views
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile... by Stefan Wolpers
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...
How To Make Your Plans Suck Less — Maarten Dalmijn at the 57th Hands-on Agile...
Stefan Wolpers42 views
360 graden fabriek by info33492
360 graden fabriek360 graden fabriek
360 graden fabriek
info33492165 views
aATP - New Correlation Confirmation Feature.pptx by EsatEsenek1
aATP - New Correlation Confirmation Feature.pptxaATP - New Correlation Confirmation Feature.pptx
aATP - New Correlation Confirmation Feature.pptx
EsatEsenek1205 views
How Workforce Management Software Empowers SMEs | TraQSuite by TraQSuite
How Workforce Management Software Empowers SMEs | TraQSuiteHow Workforce Management Software Empowers SMEs | TraQSuite
How Workforce Management Software Empowers SMEs | TraQSuite
TraQSuite6 views
predicting-m3-devopsconMunich-2023-v2.pptx by Tier1 app
predicting-m3-devopsconMunich-2023-v2.pptxpredicting-m3-devopsconMunich-2023-v2.pptx
predicting-m3-devopsconMunich-2023-v2.pptx
Tier1 app12 views
tecnologia18.docx by nosi6702
tecnologia18.docxtecnologia18.docx
tecnologia18.docx
nosi67025 views
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P... by NimaTorabi2
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...
Unlocking the Power of AI in Product Management - A Comprehensive Guide for P...
NimaTorabi216 views
ADDO_2022_CICID_Tom_Halpin.pdf by TomHalpin9
ADDO_2022_CICID_Tom_Halpin.pdfADDO_2022_CICID_Tom_Halpin.pdf
ADDO_2022_CICID_Tom_Halpin.pdf
TomHalpin95 views
DRYiCE™ iAutomate: AI-enhanced Intelligent Runbook Automation by HCLSoftware
DRYiCE™ iAutomate: AI-enhanced Intelligent Runbook AutomationDRYiCE™ iAutomate: AI-enhanced Intelligent Runbook Automation
DRYiCE™ iAutomate: AI-enhanced Intelligent Runbook Automation
HCLSoftware6 views

Easy REST APIs with Jersey and RestyGWT

  • 1. Easy REST APIs with Jersey and RestyGWT David Chandler turbomanage.wordpress.com
  • 2. why RestyGWT? Ease of GWT-RPC Power of Command pattern Less boilerplate Easier testing
  • 4. map JSON public class YqlResponse {
 public YqlQuery query;
 
 public static class YqlQuery {
 public YqlResults results;
 
 public static class YqlResults {
 public List<Quote> quote;
 }
 }
 }
 no annotations needed
  • 5. create a service API @Path("http://query.yahooapis.com/v1/public")
 public interface QuoteService extends RestService {
 @GET
 @Path("yql")
 public void get(
 @QueryParam("q") String query,
 @QueryParam("env") String env,
 @QueryParam("format") String format,
 MethodCallback<YqlResponse> callback);
 }

  • 6. invoke the service private static final QuoteService svc = GWT.create(QuoteService.class);
 
 @Override
 public void load(LoaderDemo.QuoteRequest input, final Callback<ListLoadResult<Quote>, Throwable> callback) {
 svc.get(input.getYql(), ENV, FORMAT, new MethodCallback<YqlResponse>() {
 @Override
 public void onFailure(Method method, Throwable throwable) {
 Info.display("QuoteProxy", "failure");
 callback.onFailure(throwable);
 }
 
 @Override
 public void onSuccess(Method method, YqlResponse yqlResponse) {
 List<Quote> quotes = yqlResponse.query.results.quote;
 Info.display("QuoteProxy", "success");
 callback.onSuccess(new ListLoadResultBean<Quote>(quotes));
 }
 });
 }

  • 7. simple CRUD API public interface RestApi<T> extends RestService {
 
 @GET
 @Path("get")
 public void get(@QueryParam("id")Long id, MethodCallback<T> callback);
 
 @GET
 @Path("all")
 public void listAll(MethodCallback<ListResponse<T>> callback);
 
 @POST
 @Path("save")
 public void save(T obj, MethodCallback<T> callback);
 
 @POST
 @Path("saveMany")
 public void saveMany(List<T> obj, MethodCallback<Integer> callback);
 
 @POST
 @Path("delete")
 public void delete(Long id, MethodCallback<Integer> callback);
 
 }

  • 8. not much here! minimal boilerplate @Path("/api/note")
 public interface NoteItemRestService extends RestApi<Note> { }
 
 private static final NoteItemRestService service = GWT.create(NoteItemRestService.class);
 
 public void addNote(Display display, long listId, Note item)
 {
 NoteList noteList = App.getNoteListService().getNoteList(listId);
 // All are 0-based for consistency with GWT constants
 item.listId = listId;
 service.save(item, new AppCallback<Note>(display) {
 @Override
 public void handleSuccess(Note result) {
 App.getAppModel().getAllNotes().add(0, result);
 App.getEventBus().fireEvent(new ShowMessageEvent("Note saved."));
 App.getEventBus().fireEvent(new NotesLoadedEvent(App.getAppModel().getAllNotes()));
 App.getEventBus().fireEvent(new NoteAddedEvent(result));
 }
 });
 }

  • 9. public class ProjectEntryPoint implements EntryPoint {
 
 private static DispatcherFactory dispatcherFactory = new DispatcherFactory();
 private static FilterawareDispatcher dispatcher = dispatcherFactory.cachingDispatcher();
 
 @Override
 public void onModuleLoad() {
 // Configure RestyGWT
 dispatcher.addFilter(new CORSFilter());
 Defaults.setDispatcher(dispatcher);
 
 LoaderDemo loaderDemo = new LoaderDemo();
 RootPanel.get().add(loaderDemo);
 }
 
 } ListAllNotesAction, ListAllNotesResult,
 AddNoteAction, AddNoteResult, … Command pattern
  • 10. server side @Path("api/note")
 public class NoteDao extends RestServiceDao<Note>
 { 
 private static final Logger LOG = Logger.getLogger(NoteDao.class.getName());
 
 @Override
 @Path("all")
 @GET
 public ListWrapper<Note> findAll() {
 User user = AuthFilter.getUser();
 List<Note> notes = this.listByOwner(user);
 return new ListWrapper<Note>(notes);
 } . . . }
  • 11. Objectify + Jersey @Produces(MediaType.APPLICATION_JSON)
 public class RestServiceDao<T extends Owned> extends ObjectifyDao<T>
 {
 
 public T getForOwner() {
 User user = AuthFilter.getUser();
 T obj = null;
 try {
 obj = this.getByOwner(user);
 return obj;
 } catch (TooManyResultsException e) {
 throw new WebApplicationException(e);
 }
 }
 
 public ListWrapper<T> findAll() {
 User user = AuthFilter.getUser();
 List<T> userAll = this.listByOwner(user);
 return new ListWrapper<T>(userAll);
 } . . . }

  • 12. getting Jersey pom.xml <dependency>
 <groupId>org.glassfish.jersey.containers</groupId>
 <!-- if your container implements Servlet API older than 3.0, 
 use "jersey-container-servlet-core" -->
 <artifactId>jersey-container-servlet-core</artifactId>
 <version>2.7</version>
 </dependency>
 <!-- workaround for https://java.net/jira/browse/JERSEY-2459 -->
 <dependency>
 <groupId>org.glassfish.hk2</groupId>
 <artifactId>hk2-api</artifactId>
 <version>2.3.0-b09</version>
 </dependency>
 <dependency>
 <groupId>com.fasterxml.jackson.jaxrs</groupId>
 <artifactId>jackson-jaxrs-json-provider</artifactId>
 <version>2.3.2</version>
 </dependency>

  • 13. Jersey config web.xml <servlet>
 <servlet-name>jerseyServlet</servlet-name>
 <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
 <init-param>
 <param-name>jersey.config.server.provider.packages</param-name>
 <param-value>com.example.listmaker.server</param-value>
 </init-param>
 <init-param>
 <!-- speed up initial Jersey loading by deactivating WADL -->
 <param-name>jersey.config.server.wadl.disableWadl</param-name>
 <param-value>true</param-value>
 </init-param>
 <init-param>
 <param-name>jersey.config.server.provider.classnames</param-name>
 <param-value>org.glassfish.jersey.filter.LoggingFilter</param-value>
 </init-param>
 <load-on-startup>1</load-on-startup>
 </servlet>
 
 <servlet-mapping>
 <servlet-name>jerseyServlet</servlet-name>
 <url-pattern>/listmaker/*</url-pattern>
 </servlet-mapping>

  • 14. what about auth? AuthFilter.java // if an API call, return JSON response
 if (path.startsWith("/listmaker/api")) {
 ((HttpServletResponse) resp).setStatus(401);
 resp.setContentType(MediaType.TEXT_PLAIN);
 resp.getWriter().write("User must log in");
 } else {
 // otherwise redirect
 httpRes.sendRedirect(LOGIN_FORM);
 } <filter>
 <filter-name>AuthFilter</filter-name>
 <filter-class>com.turbomanage.gwt.server.servlet.AuthFilter</filter-class>
 </filter>
 <filter-mapping>
 <filter-name>AuthFilter</filter-name>
 <url-pattern>/listmaker/*</url-pattern>
 </filter-mapping>

  • 15. exception handling @Override
 public void onFailure(Method method, Throwable throwable) {
 String url = method.builder.getUrl();
 
 App.getLogger().log(Level.SEVERE, "Error calling service " + url, throwable);
 try {
 // Decode the exception
 if (throwable instanceof FailedStatusCodeException) {
 FailedStatusCodeException sce = (FailedStatusCodeException) throwable;
 App.getLogger().log(Level.SEVERE, "Service returned " + sce.getStatusCode() + sce.getMessage());
 if (401 == sce.getStatusCode()) {
 Window.Location.replace(LOGIN_FORM);
 } else if (500 == sce.getStatusCode()) {
 if ("UserNotRegisteredException".equals(sce.getMessage())) {
 Window.Location.replace(SIGNUP_URL);
 }
 }
 }
 handleFailure(throwable);
 } finally {
 reset(null);
 }
 }

  • 16. application error handling service.save(item, new AppCallback<Note>(display) {
 @Override
 public void handleSuccess(Note result) {
 . . . }
 }); public abstract class AppCallback<R> implements MethodCallback<R> {
 
 private final Display display;
 
 public AppCallback() {
 this.display = null;
 }
 
 public AppCallback(Display display) {
 this.display = display;
 display.startProcessing();
 } . . . }
  • 17. finer points Text, JSON, XML via direct API — res.get()… CachingRetryingDispatcher ModelChangeEvent Objects with final fields (@JsonCreator) Polymorphism (@JsonSubTypes)
  • 18. same obj on client / server? older versions of RestyGWT used Jackson 1.7 RestyGWT 2.0 uses Jackson 2.3 so you can now use the same annotations on client and server and therefore the same POJOs (yeah)! use @JsonIgnore for server-only fields (like Ref)
  • 19. Please rate this session at gwtcreate.com/agenda src github.com/turbomanage/listmaker David Chandler turbomanage.wordpress.com resty-gwt.github.io