Skip to content

Commit 1e48fb7

Browse files
committed
Merge pull request #8 from imsweb/retrofit-2.0
Retrofit 2.0
2 parents fd15127 + 4bf4792 commit 1e48fb7

26 files changed

Lines changed: 406 additions & 397 deletions

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Download [the latest JAR][1] or grab via Maven:
2929
<dependency>
3030
<groupId>com.imsweb</groupId>
3131
<artifactId>seerapi-client-java</artifactId>
32-
<version>2.0</version>
32+
<version>3.0</version>
3333
</dependency>
3434
```
3535

@@ -73,15 +73,15 @@ Each set of APIs are broken into their own service. Here are the services:
7373
A glossary of cancer-related terms.
7474

7575
```java
76-
api.glossary().getById("latest", "4ffd7623a3dd635c99d38e2d");
76+
api.glossary().getById("latest", "4ffd7623a3dd635c99d38e2d").execute().body()
7777
```
7878

7979
### Disease (rest/disease)
8080

8181
A searchable database of hematopoietic and lymphoid neoplasms and solid tumor diseases.
8282

8383
```java
84-
api.disease().samePrimaries("9870/3", "9872/3", "2010")
84+
api.disease().samePrimaries("9870/3", "9872/3", "2010").execute().body()
8585
```
8686

8787
### NAACCR (rest/naaccr)
@@ -90,15 +90,15 @@ The NAACCR API provides programmatic access to documentation for the NAACCR Stan
9090
field level documentation as well as information about file layout.
9191

9292
```java
93-
api.naaccr().field("14", 12)
93+
api.naaccr().field("14", 12).execute().body()
9494
```
9595

9696
### RX (rest/rx)
9797

9898
A searchable database for coding oncology drug and regimen treatment categories in cancer registries.
9999

100100
```java
101-
api.rx().getById("latest", "53c44b01102c1290262dc8b2");
101+
api.rx().getById("latest", "53c44b01102c1290262dc8b2").execute().body()
102102
```
103103

104104
### SEER Incidence Site Recode (rest/recode)
@@ -109,15 +109,15 @@ cancer incidence data. For example, there is a section of the SEER Cancer Statis
109109
groupings in a site recode variable. The site recode variables are added to SEER databases as a convenience for researchers.
110110

111111
```java
112-
api.siteRecode().siteGroup("C619", "8000");
112+
api.siteRecode().siteGroup("C619", "8000").execute().body()
113113
```
114114

115115
### Site-specific Surgery Codes (rest/surgery)
116116

117117
The site-specific surgery tables available on the SEER website.
118118

119119
```java
120-
api.surgery().tables();
120+
api.surgery().tables().execute().body()
121121
```
122122

123123
### Staging
@@ -128,7 +128,7 @@ improve data quality by standardizing rules for timing, clinical and pathologic
128128
systems for all cancer sites.
129129

130130
```
131-
api.staging().schemaById("cs", "02.05.50", "brain");
131+
api.staging().schemaById("cs", "02.05.50", "brain").execute().body()
132132
```
133133

134134
For a complete description of all available API inputs and outputs, see the SEER*API

build.gradle

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ plugins {
88
}
99

1010
group = 'com.imsweb'
11-
version = '2.0'
11+
version = '3.0'
1212
description = 'Java client library for SEER*API'
1313

1414
println "Starting build using ${Jvm.current()}"
@@ -21,12 +21,8 @@ repositories {
2121
}
2222

2323
dependencies {
24-
compile 'com.squareup.okhttp:okhttp:2.4.0'
25-
compile('com.squareup.retrofit:retrofit:1.9.0') {
26-
exclude module: 'gson' // since Jackson is used, this is not needed
27-
}
28-
29-
compile 'com.fasterxml.jackson.core:jackson-databind:2.5.3'
24+
compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
25+
compile 'com.squareup.retrofit:converter-jackson:2.0.0-beta2'
3026

3127
testCompile 'junit:junit:4.11'
3228
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright (C) 2015 Information Management Services, Inc.
3+
*/
4+
package com.imsweb.seerapi.client;
5+
6+
import java.io.IOException;
7+
8+
import com.fasterxml.jackson.databind.ObjectMapper;
9+
import com.squareup.okhttp.Interceptor;
10+
import com.squareup.okhttp.Response;
11+
12+
/**
13+
* Interceptor to catch all non-200 responses and convert them to exceptions.
14+
*/
15+
public class ErrorInterceptor implements Interceptor {
16+
17+
@Override
18+
public Response intercept(Chain chain) throws IOException {
19+
Response response = chain.proceed(chain.request());
20+
21+
if (response.code() != 200) {
22+
// convert body to error response
23+
ErrorResponse error = null;
24+
if (response.body() != null) {
25+
try {
26+
error = new ObjectMapper().readValue(response.body().byteStream(), ErrorResponse.class);
27+
}
28+
catch (IOException e) {
29+
// sometimes the error message is not right format (like for 404 errors)
30+
}
31+
}
32+
33+
String message = error == null ? "Error code " + response.code() : error.getMessage();
34+
35+
switch (response.code()) {
36+
case 401: // unauthorized
37+
throw new NotAuthorizedException(message);
38+
case 400: // bad request
39+
throw new BadRequestException(message);
40+
case 404:
41+
throw new NotFoundException(message);
42+
default:
43+
throw new SeerApiException(message);
44+
}
45+
}
46+
47+
return response;
48+
}
49+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (C) 2015 Information Management Services, Inc.
3+
*/
4+
package com.imsweb.seerapi.client;
5+
6+
public class NotFoundException extends SeerApiException {
7+
8+
public NotFoundException() {
9+
super();
10+
}
11+
12+
public NotFoundException(String message) {
13+
super(message);
14+
}
15+
16+
public NotFoundException(String message, Throwable cause) {
17+
super(message, cause);
18+
}
19+
20+
public NotFoundException(Throwable cause) {
21+
super(cause);
22+
}
23+
24+
}

src/main/java/com/imsweb/seerapi/client/SeerApi.java

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,21 @@
66
import java.io.File;
77
import java.io.FileInputStream;
88
import java.io.IOException;
9+
import java.text.DateFormat;
10+
import java.text.SimpleDateFormat;
911
import java.util.Properties;
1012

11-
import retrofit.RestAdapter;
13+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
14+
import com.fasterxml.jackson.annotation.JsonInclude;
15+
import com.fasterxml.jackson.databind.ObjectMapper;
16+
import com.fasterxml.jackson.databind.SerializationFeature;
17+
import com.squareup.okhttp.Interceptor;
18+
import com.squareup.okhttp.OkHttpClient;
19+
import com.squareup.okhttp.Request;
20+
import com.squareup.okhttp.Response;
21+
22+
import retrofit.JacksonConverterFactory;
23+
import retrofit.Retrofit;
1224

1325
import com.imsweb.seerapi.client.disease.DiseaseService;
1426
import com.imsweb.seerapi.client.glossary.GlossaryService;
@@ -23,79 +35,122 @@
2335
*/
2436
public final class SeerApi {
2537

26-
RestAdapter _restAdapter;
38+
private Retrofit _retroFit;
2739

2840
/**
2941
* Creates a client API root object
3042
* @param baseUrl base URL for API
3143
* @param apiKey API key
3244
*/
33-
private SeerApi(String baseUrl, String apiKey) {
34-
if (baseUrl.endsWith("/"))
35-
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
36-
37-
_restAdapter = new RestAdapter.Builder()
38-
.setEndpoint(baseUrl)
39-
.setConverter(new SeerApiJacksonConverter())
40-
.setRequestInterceptor(new SeerApiRequestInterceptor(apiKey))
41-
.setErrorHandler(new SeerApiErrorHandler())
45+
private SeerApi(String baseUrl, final String apiKey) {
46+
if (!baseUrl.endsWith("/"))
47+
baseUrl += "/";
48+
49+
OkHttpClient client = new OkHttpClient();
50+
client.interceptors().add(new Interceptor() {
51+
@Override
52+
public Response intercept(Chain chain) throws IOException {
53+
Request original = chain.request();
54+
55+
// add the api key to all requests
56+
Request request = original.newBuilder()
57+
.header("Accept", "application/json")
58+
.header("X-SEERAPI-Key", apiKey)
59+
.method(original.method(), original.body())
60+
.build();
61+
62+
return chain.proceed(request);
63+
}
64+
});
65+
client.interceptors().add(new ErrorInterceptor());
66+
67+
_retroFit = new Retrofit.Builder()
68+
.baseUrl(baseUrl)
69+
.addConverterFactory(JacksonConverterFactory.create(getMapper()))
70+
.client(client)
4271
.build();
4372
}
4473

74+
/**
75+
* Return the internal ObjectMapper
76+
* @return
77+
*/
78+
protected static ObjectMapper getMapper() {
79+
ObjectMapper mapper = new ObjectMapper();
80+
81+
// do not write null values
82+
mapper.configure(SerializationFeature.WRITE_NULL_MAP_VALUES, false);
83+
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
84+
85+
mapper.setVisibilityChecker(mapper.getSerializationConfig().getDefaultVisibilityChecker()
86+
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
87+
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
88+
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
89+
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));
90+
91+
// set Date objects to output in readable customized format
92+
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
93+
94+
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
95+
mapper.setDateFormat(dateFormat);
96+
97+
return mapper;
98+
}
99+
45100
/**
46101
* Return the disease service
47102
* @return an interface to all the disease APIs
48103
*/
49104
public DiseaseService disease() {
50-
return _restAdapter.create(DiseaseService.class);
105+
return _retroFit.create(DiseaseService.class);
51106
}
52107

53108
/**
54109
* Return the glossary service
55110
* @return an interface to all the glossary APIs
56111
*/
57112
public GlossaryService glossary() {
58-
return _restAdapter.create(GlossaryService.class);
113+
return _retroFit.create(GlossaryService.class);
59114
}
60115

61116
/**
62117
* Return the NAACCR service
63118
* @return an inteface to all the NAACCR APIs
64119
*/
65120
public NaaccrService naaccr() {
66-
return _restAdapter.create(NaaccrService.class);
121+
return _retroFit.create(NaaccrService.class);
67122
}
68123

69124
/**
70125
* Return the Rx service
71126
* @return an inteface to all the Rx APIs
72127
*/
73128
public RxService rx() {
74-
return _restAdapter.create(RxService.class);
129+
return _retroFit.create(RxService.class);
75130
}
76131

77132
/**
78133
* Return the site recode service
79134
* @return an interface to all the site recode APIs
80135
*/
81136
public SiteRecodeService siteRecode() {
82-
return _restAdapter.create(SiteRecodeService.class);
137+
return _retroFit.create(SiteRecodeService.class);
83138
}
84139

85140
/**
86141
* Return the staging service
87142
* @return an interface to all the staging APIs
88143
*/
89144
public StagingService staging() {
90-
return _restAdapter.create(StagingService.class);
145+
return _retroFit.create(StagingService.class);
91146
}
92147

93148
/**
94149
* Return the surgery service
95150
* @return an interface to all the surgery APIs
96151
*/
97152
public SurgeryService surgery() {
98-
return _restAdapter.create(SurgeryService.class);
153+
return _retroFit.create(SurgeryService.class);
99154
}
100155

101156
/**
@@ -104,7 +159,7 @@ public SurgeryService surgery() {
104159
public static class Builder {
105160

106161
// default base URL
107-
private static final String _SEERAPI_URL = "https://api.seer.cancer.gov/rest";
162+
private static final String _SEERAPI_URL = "https://api.seer.cancer.gov/rest/";
108163

109164
// environment variable for URL and API key
110165
private static final String _ENV_URL = "SEER_API_URL";

src/main/java/com/imsweb/seerapi/client/SeerApiErrorHandler.java

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)