Skip to content
This repository was archived by the owner on Mar 31, 2025. It is now read-only.

Commit 86de3f4

Browse files
authored
Merge pull request #15 from hubrick/feature/allow-object-mapper-injection
allow injection of custom object mapper
2 parents ab16d5b + 0bbf382 commit 86de3f4

File tree

8 files changed

+192
-13
lines changed

8 files changed

+192
-13
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ Table<Actor> actorTable = base.table("Actors", Actor.class);
296296
Actor newActor = new Actor();
297297
newActor.setName("Neuer Actor");
298298
Actor test = actorTable.create(newActor);
299+
299300
```
300301

301302
Detailed example see [TableDestroyTest.java](https://github.com/Sybit-Education/airtable.java/blob/develop/src/test/java/com/sybit/airtable/TableCreateRecordTest.java)
@@ -370,6 +371,7 @@ We use [Gradle](https://gradle.org) to compile and package project:
370371
+ build jar: `./gradlew jar` (The built JARs will be placed under `build/libs`.)
371372

372373
## Testing
374+
373375
There are JUnit tests and integration tests to verify the API.
374376
The integration tests are based on the Airtable template [Movies](https://airtable.com/templates/groups-clubs-and-hobbies/exprTnrH3YV8Vv9BI/favorite-movies) which could be created in your account.
375377
For testing, the JSON-responses are mocked by [WireMock](http://wiremock.org/).

build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ task integrationTest(type: Test) {
143143
}
144144
}
145145

146-
147146
publishing {
148147
publications {
149148

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package com.sybit.airtable;
2+
3+
import com.fasterxml.jackson.core.JsonProcessingException;
4+
import com.mashape.unirest.http.ObjectMapper;
5+
import com.sybit.airtable.exception.AirtableException;
6+
import com.sybit.airtable.movies.ActorSerializedNames;
7+
import com.sybit.airtable.movies.Movie;
8+
import com.sybit.airtable.mock.WireMockBaseTest;
9+
import org.apache.http.client.HttpResponseException;
10+
import org.junit.Before;
11+
import org.junit.Test;
12+
13+
import java.io.IOException;
14+
import java.util.List;
15+
16+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
17+
import static com.github.tomakehurst.wiremock.client.WireMock.any;
18+
import static com.github.tomakehurst.wiremock.client.WireMock.anyUrl;
19+
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
20+
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertNotNull;
22+
23+
/**
24+
* Created by kobisuissa on 18/04/17.
25+
*/
26+
public class TableSelectJacksonOMTest extends WireMockBaseTest {
27+
28+
@Before
29+
public void setup() throws AirtableException {
30+
airtable.configure(new ObjectMapper() {
31+
32+
final com.fasterxml.jackson.databind.ObjectMapper objectMapper = new com.fasterxml.jackson.databind.ObjectMapper();
33+
34+
@Override
35+
public <T> T readValue(final String value, final Class<T> valueType) {
36+
try {
37+
return objectMapper.readValue(value, valueType);
38+
} catch (IOException e) {
39+
throw new RuntimeException(e);
40+
}
41+
}
42+
43+
@Override
44+
public String writeValue(final Object value) {
45+
try {
46+
return objectMapper.writeValueAsString(value);
47+
} catch (JsonProcessingException e) {
48+
throw new RuntimeException(e);
49+
}
50+
}
51+
});
52+
airtable.setEndpointUrl("http://localhost:8080/v0");
53+
54+
//set 404 as default
55+
stubFor(any(anyUrl())
56+
.atPriority(10)
57+
.willReturn(aResponse()
58+
.withStatus(404)
59+
.withBody("{\"error\":{\"type\":\"NOT_FOUND\",\"message\":\"Not found\"}}")));
60+
61+
}
62+
63+
@Test
64+
public void testSelectTable() throws AirtableException, HttpResponseException {
65+
66+
Base base = airtable.base("appe9941ff07fffcc");
67+
68+
List<Movie> retval = base.table("Movies", Movie.class).select();
69+
assertNotNull(retval);
70+
assertEquals(10, retval.size());
71+
Movie mov = retval.get(0);
72+
assertEquals("Sister Act", mov.getName());
73+
}
74+
75+
@Test
76+
public void testSelectTableMaxRecords() throws AirtableException, HttpResponseException {
77+
78+
Base base = airtable.base("appe9941ff07fffcc");
79+
80+
List<Movie> retval = base.table("Movies", Movie.class).select(2);
81+
assertNotNull(retval);
82+
assertEquals(2, retval.size());
83+
Movie mov = retval.get(0);
84+
assertEquals("Sister Act", mov.getName());
85+
}
86+
87+
@Test
88+
public void testSelectTableSorted() throws AirtableException, HttpResponseException {
89+
90+
Base base = airtable.base("appe9941ff07fffcc");
91+
Table table = base.table("Movies", Movie.class);
92+
93+
List<Movie> retval = table.select(new Sort("Name", Sort.Direction.asc));
94+
assertNotNull(retval);
95+
assertEquals(10, retval.size());
96+
Movie mov = retval.get(0);
97+
assertEquals("Billy Madison", mov.getName());
98+
99+
retval = table.select(new Sort("Name", Sort.Direction.desc));
100+
assertNotNull(retval);
101+
assertEquals(10, retval.size());
102+
mov = retval.get(0);
103+
assertEquals("You've got Mail", mov.getName());
104+
105+
}
106+
107+
@Test
108+
public void testSelectTableView() throws AirtableException, HttpResponseException {
109+
110+
Base base = airtable.base("appe9941ff07fffcc");
111+
112+
List<Movie> retval = base.table("Movies", Movie.class).select("Main View");
113+
assertNotNull(retval);
114+
assertEquals(10, retval.size());
115+
Movie mov = retval.get(0);
116+
assertEquals("The Godfather", mov.getName());
117+
}
118+
119+
@Test(expected = AirtableException.class)
120+
public void testSelectNonExistingTable() throws AirtableException, HttpResponseException {
121+
122+
Base base = airtable.base("appe9941ff07fffcc");
123+
124+
List<Movie> retval = base.table("NotExists", Movie.class).select();
125+
assertNotNull(retval);
126+
}
127+
128+
@Test
129+
public void testSelectWithSerializedNames() throws AirtableException, HttpResponseException {
130+
131+
Base base = airtable.base("appe9941ff07fffcc");
132+
133+
List<ActorSerializedNames> retval = base.table("SerializedNames", ActorSerializedNames.class).select();
134+
assertNotNull(retval);
135+
assertEquals("Marlon Brando", retval.get(0).getName());
136+
}
137+
138+
}

src/main/java/com/sybit/airtable/Airtable.java

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package com.sybit.airtable;
88

99

10+
import com.mashape.unirest.http.ObjectMapper;
1011
import com.mashape.unirest.http.Unirest;
1112
import com.sybit.airtable.converter.ListConverter;
1213
import com.sybit.airtable.converter.MapConverter;
@@ -54,11 +55,24 @@ public class Airtable {
5455
* Configure, <code>AIRTABLE_API_KEY</code> passed by Java property, enviroment variable
5556
* or within credentials.properties.
5657
*
57-
* @return configured Airtable object.
58+
* @return An Airtable instance configured with GsonObjectMapper
5859
* @throws com.sybit.airtable.exception.AirtableException Missing API-Key
5960
*/
6061
@SuppressWarnings("UnusedReturnValue")
6162
public Airtable configure() throws AirtableException {
63+
return this.configure(new GsonObjectMapper());
64+
}
65+
66+
/**
67+
* Configure, <code>AIRTABLE_API_KEY</code> passed by Java property, enviroment variable
68+
* or within credentials.properties.
69+
*
70+
* @param objectMapper A custom ObjectMapper implementation
71+
* @return An Airtable instance configured with supplied ObjectMapper
72+
* @throws com.sybit.airtable.exception.AirtableException Missing API-Key
73+
*/
74+
@SuppressWarnings("UnusedReturnValue")
75+
public Airtable configure(ObjectMapper objectMapper) throws AirtableException {
6276

6377
LOG.info( "System-Property: Using Java property '-D" + AIRTABLE_API_KEY + "' to get apikey.");
6478
String airtableApi = System.getProperty(AIRTABLE_API_KEY);
@@ -71,7 +85,7 @@ public Airtable configure() throws AirtableException {
7185
airtableApi = getCredentialProperty(AIRTABLE_API_KEY);
7286
}
7387

74-
return this.configure(airtableApi);
88+
return this.configure(airtableApi, objectMapper);
7589
}
7690

7791

@@ -80,12 +94,25 @@ public Airtable configure() throws AirtableException {
8094
* Configure Airtable.
8195
*
8296
* @param apiKey API-Key of Airtable.
83-
* @return
97+
* @return An Airtable instance configured with GsonObjectMapper
8498
* @throws com.sybit.airtable.exception.AirtableException Missing API-Key
8599
*/
86100
@SuppressWarnings("WeakerAccess")
87101
public Airtable configure(String apiKey) throws AirtableException {
88-
return configure(new Configuration(apiKey, Configuration.ENDPOINT_URL));
102+
return configure(apiKey, new GsonObjectMapper());
103+
}
104+
105+
/**
106+
* Configure Airtable.
107+
*
108+
* @param apiKey API-Key of Airtable.
109+
* @param objectMapper A custom ObjectMapper implementation
110+
* @return
111+
* @throws com.sybit.airtable.exception.AirtableException Missing API-Key
112+
*/
113+
@SuppressWarnings("WeakerAccess")
114+
public Airtable configure(String apiKey, ObjectMapper objectMapper) throws AirtableException {
115+
return configure(new Configuration(apiKey, Configuration.ENDPOINT_URL), objectMapper);
89116
}
90117

91118
/**
@@ -96,6 +123,19 @@ public Airtable configure(String apiKey) throws AirtableException {
96123
*/
97124
@SuppressWarnings("WeakerAccess")
98125
public Airtable configure(Configuration config) throws AirtableException {
126+
return configure(config, new GsonObjectMapper());
127+
}
128+
129+
130+
/**
131+
*
132+
* @param config
133+
* @param objectMapper A custom ObjectMapper implementation
134+
* @return
135+
* @throws com.sybit.airtable.exception.AirtableException Missing API-Key or Endpoint
136+
*/
137+
@SuppressWarnings("WeakerAccess")
138+
public Airtable configure(Configuration config, ObjectMapper objectMapper) throws AirtableException {
99139
if(config.getApiKey() == null) {
100140
throw new AirtableException("Missing Airtable API-Key");
101141
}
@@ -113,22 +153,21 @@ public Airtable configure(Configuration config) throws AirtableException {
113153
setProxy(config.getEndpointUrl());
114154

115155
// Only one time
116-
Unirest.setObjectMapper(new GsonObjectMapper());
156+
Unirest.setObjectMapper(objectMapper);
117157

118-
119158
// Add specific Converter for Date
120159
DateTimeConverter dtConverter = new DateConverter();
121160
ListConverter lConverter = new ListConverter();
122161
MapConverter thConverter = new MapConverter();
123-
162+
124163
lConverter.setListClass(Attachment.class);
125164
thConverter.setMapClass(Thumbnail.class);
126165
dtConverter.setPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
127-
166+
128167
ConvertUtils.register(dtConverter, Date.class);
129168
ConvertUtils.register(lConverter, List.class);
130169
ConvertUtils.register(thConverter, Map.class);
131-
170+
132171

133172
return this;
134173
}
@@ -142,8 +181,8 @@ public Airtable configure(Configuration config) throws AirtableException {
142181
private void setProxy(String endpointUrl) {
143182
final String httpProxy = System.getenv("http_proxy");
144183
if(httpProxy != null
145-
&& (endpointUrl.contains("127.0.0.1")
146-
|| endpointUrl.contains("localhost"))) {
184+
&& (endpointUrl.contains("127.0.0.1")
185+
|| endpointUrl.contains("localhost"))) {
147186
LOG.info("Use Proxy: ignored for 'localhost' ann '127.0.0.1'");
148187
Unirest.setProxy(null);
149188
} else if(httpProxy != null) {

src/main/java/com/sybit/airtable/converter/MapConverter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,4 @@ public void setMapClass(Class<Thumbnail> aClass) {
131131
public Class getMapClass(){
132132
return this.mapClass;
133133
}
134-
135134
}

src/test/java/com/sybit/airtable/movies/Actor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package com.sybit.airtable.movies;
88

99

10+
1011
import com.sybit.airtable.movies.*;
1112
import com.google.gson.annotations.SerializedName;
1213
import com.sybit.airtable.vo.Attachment;

src/test/java/com/sybit/airtable/movies/Movie.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package com.sybit.airtable.movies;
88

9+
910
import com.sybit.airtable.movies.*;
1011
import com.google.gson.annotations.SerializedName;
1112
import com.sybit.airtable.vo.Attachment;

0 commit comments

Comments
 (0)