Skip to content

Commit 04f855c

Browse files
authored
Custom Exceptions: MeiliSearchException => MeiliSearchApiException + MeiliSearchConnectionException (#46)
Custom Exceptions: MeiliSearchException => MeiliSearchApiException + MeiliSearchConnectionException
1 parent 54d25f8 commit 04f855c

10 files changed

+231
-19
lines changed

src/main/java/com/meilisearch/sdk/Client.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
import com.google.gson.Gson;
77

8+
import com.meilisearch.sdk.exceptions.MeiliSearchApiException;
9+
810
/**
911
* Meilisearch client
1012
*/
@@ -32,10 +34,8 @@ public Client(Config config) {
3234
* @return Meilisearch API response
3335
* @throws Exception If an error occurs
3436
*/
35-
public Index createIndex(String uid) throws Exception {
36-
Index index = gson.fromJson(this.indexesHandler.create(uid), Index.class);
37-
index.setConfig(this.config);
38-
return index;
37+
public Index createIndex(String uid) throws Exception, MeiliSearchApiException {
38+
return this.createIndex(uid, null);
3939
}
4040

4141
/**
@@ -47,8 +47,7 @@ public Index createIndex(String uid) throws Exception {
4747
* @return Meilisearch API response
4848
* @throws Exception If an error occurs
4949
*/
50-
public Index createIndex(String uid, String primaryKey) throws Exception {
51-
// return this.indexesHandler.create(uid, primaryKey);
50+
public Index createIndex(String uid, String primaryKey) throws Exception, MeiliSearchApiException {
5251
Index index = gson.fromJson(this.indexesHandler.create(uid, primaryKey), Index.class);
5352
index.setConfig(this.config);
5453
return index;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.meilisearch.sdk.exceptions;
2+
3+
import com.meilisearch.sdk.json.GsonJsonHandler;
4+
5+
public class MeiliSearchApiException extends MeiliSearchException {
6+
7+
/**
8+
* This is class wraps errors sent by MeiliSearch API
9+
*/
10+
11+
private GsonJsonHandler gson = new GsonJsonHandler();
12+
13+
private class ApiError {
14+
public String message;
15+
public String errorCode;
16+
public String errorType;
17+
public String errorLink;
18+
}
19+
20+
public MeiliSearchApiException (String errorMessage) throws Exception {
21+
super(errorMessage);
22+
ApiError error = this.gson.decode(
23+
errorMessage,
24+
ApiError.class
25+
);
26+
this.setErrorMessage(error.message);
27+
this.setErrorCode(error.errorCode);
28+
this.setErrorType(error.errorType);
29+
this.setErrorLink(error.errorLink);
30+
}
31+
32+
public String toString() {
33+
return this.getClass().getName()
34+
+ ". Error message: " + this.errorMessage
35+
+ ". Error code: " + this.errorCode
36+
+ ". Error documentation: " + this.errorLink
37+
+ ". Error type: " + this.errorType
38+
+ ".";
39+
}
40+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.meilisearch.sdk.exceptions;
2+
3+
public class MeiliSearchCommunicationException extends MeiliSearchException {
4+
5+
public MeiliSearchCommunicationException (String errorMessage) {
6+
super(errorMessage);
7+
}
8+
9+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.meilisearch.sdk.exceptions;
2+
3+
public class MeiliSearchException extends Exception {
4+
5+
/**
6+
* This is a generic class for MeiliSearch Exception handling
7+
*/
8+
9+
String errorMessage;
10+
String errorType;
11+
String errorCode;
12+
String errorLink;
13+
14+
public MeiliSearchException (String errorMessage) {
15+
super(errorMessage);
16+
this.setErrorMessage(errorMessage);
17+
}
18+
19+
public String getMessage () {
20+
return this.errorMessage;
21+
}
22+
23+
public String getErrorType () {
24+
return this.errorType;
25+
}
26+
27+
public String getErrorCode () {
28+
return this.errorCode;
29+
}
30+
31+
public String getErrorLink () {
32+
return this.errorLink;
33+
}
34+
35+
public void setErrorMessage (String errorMessage) {
36+
this.errorMessage = errorMessage;
37+
}
38+
39+
public void setErrorType (String errorType) {
40+
this.errorType = errorType;
41+
}
42+
43+
public void setErrorCode (String errorCode) {
44+
this.errorCode = errorCode;
45+
}
46+
47+
public void setErrorLink (String errorLink) {
48+
this.errorLink = errorLink;
49+
}
50+
51+
public String toString() {
52+
return this.getClass().getName()
53+
+ ". Error message: " + this.errorMessage
54+
+ ".";
55+
}
56+
}

src/main/java/com/meilisearch/sdk/IndexesHandler.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.google.gson.JsonObject;
44

5+
import com.meilisearch.sdk.exceptions.MeiliSearchApiException;
6+
57
/**
68
* Wrapper around the MeilisearchHttpRequest class to ease usage for Meilisearch indexes
79
*/
@@ -24,7 +26,7 @@ class IndexesHandler {
2426
* @return Meilisearch API response
2527
* @throws Exception If something goes wrong
2628
*/
27-
String create(String uid) throws Exception {
29+
String create(String uid) throws Exception, MeiliSearchApiException {
2830
return this.create(uid, null);
2931
}
3032

@@ -36,13 +38,12 @@ String create(String uid) throws Exception {
3638
* @return Meilisearch API response
3739
* @throws Exception If something goes wrong
3840
*/
39-
String create(String uid, String primaryKey) throws Exception {
41+
String create(String uid, String primaryKey) throws Exception, MeiliSearchApiException {
4042
JsonObject params = new JsonObject();
4143
params.addProperty("uid", uid);
4244
if (primaryKey != null) {
4345
params.addProperty("primaryKey", primaryKey);
4446
}
45-
4647
return meilisearchHttpRequest.post("/indexes", params.toString());
4748
}
4849

src/main/java/com/meilisearch/sdk/MeiliSearchHttpRequest.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.meilisearch.sdk.http.factory.RequestFactory;
77
import com.meilisearch.sdk.http.request.HttpMethod;
88
import com.meilisearch.sdk.http.response.HttpResponse;
9+
import com.meilisearch.sdk.exceptions.MeiliSearchApiException;
910

1011
import java.util.Collections;
1112

@@ -24,30 +25,42 @@ public MeiliSearchHttpRequest(AbstractHttpClient client, RequestFactory factory)
2425
}
2526

2627

27-
public String get(String api) throws Exception {
28+
public String get(String api) throws Exception, MeiliSearchApiException {
2829
return this.get(api, "");
2930
}
3031

31-
String get(String api, String param) throws Exception {
32+
String get(String api, String param) throws Exception, MeiliSearchApiException {
3233
HttpResponse<?> httpResponse = this.client.get(factory.create(HttpMethod.GET, api + param, Collections.emptyMap(), null));
34+
if (httpResponse.getStatusCode() >= 400) {
35+
throw new MeiliSearchApiException(httpResponse.getContent().toString());
36+
}
3337
return new String(httpResponse.getContentAsBytes());
3438
}
3539

3640

37-
String post(String api, String body) throws Exception {
41+
String post(String api, String body) throws Exception, MeiliSearchApiException {
3842
HttpResponse<?> httpResponse = this.client.post(factory.create(HttpMethod.POST, api, Collections.emptyMap(), body));
43+
if (httpResponse.getStatusCode() >= 400) {
44+
throw new MeiliSearchApiException(httpResponse.getContent().toString());
45+
}
3946
return new String(httpResponse.getContentAsBytes());
4047
}
4148

4249

43-
String put(String api, String body) throws Exception {
50+
String put(String api, String body) throws Exception, MeiliSearchApiException {
4451
HttpResponse<?> httpResponse = this.client.put(factory.create(HttpMethod.PUT, api, Collections.emptyMap(), body));
52+
if (httpResponse.getStatusCode() >= 400) {
53+
throw new MeiliSearchApiException(httpResponse.getContent().toString());
54+
}
4555
return new String(httpResponse.getContentAsBytes());
4656
}
4757

4858

49-
String delete(String api) throws Exception {
59+
String delete(String api) throws Exception, MeiliSearchApiException {
5060
HttpResponse<?> httpResponse = this.client.put(factory.create(HttpMethod.DELETE, api, Collections.emptyMap(), null));
61+
if (httpResponse.getStatusCode() >= 400) {
62+
throw new MeiliSearchApiException(httpResponse.getContent().toString());
63+
}
5164
return new String(httpResponse.getContentAsBytes());
5265
}
5366
}

src/main/java/com/meilisearch/sdk/http/DefaultHttpClient.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,18 @@ private HttpResponse<?> execute(HttpRequest<?> request) throws IOException {
5353
connection.getOutputStream().write(request.getContentAsBytes());
5454
}
5555

56-
InputStream errorStream = connection.getErrorStream();
57-
InputStream contentStream = (errorStream != null ? errorStream : connection.getInputStream());
56+
if (connection.getResponseCode() >= 400) {
57+
return new BasicHttpResponse(
58+
Collections.emptyMap(),
59+
connection.getResponseCode(),
60+
new BufferedReader(new InputStreamReader(connection.getErrorStream())).lines().collect(Collectors.joining("\n"))
61+
);
62+
}
5863

5964
return new BasicHttpResponse(
6065
Collections.emptyMap(),
6166
connection.getResponseCode(),
62-
new BufferedReader(new InputStreamReader(contentStream)).lines().collect(Collectors.joining("\n"))
67+
new BufferedReader(new InputStreamReader(connection.getInputStream())).lines().collect(Collectors.joining("\n"))
6368
);
6469
}
6570

src/test/java/com/meilisearch/integration/ClientTest.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
import static org.junit.jupiter.api.Assertions.*;
1313

14+
import com.meilisearch.sdk.exceptions.MeiliSearchApiException;
15+
1416
@Tag("integration")
1517
public class ClientTest extends AbstractIT {
1618

@@ -53,6 +55,22 @@ public void testCreateIndexWithPrimaryKey() throws Exception {
5355
client.deleteIndex(index.getUid());
5456
}
5557

58+
/**
59+
* Test Index creation error: already exists
60+
*/
61+
@Test
62+
public void testCreateIndexAlreadyExists() throws Exception {
63+
String indexUid = "CreateIndexAlreadyExists";
64+
Index index = client.createIndex(indexUid, this.primaryKey);
65+
assertEquals(index.getUid(), indexUid);
66+
assertEquals(index.getPrimaryKey(), this.primaryKey);
67+
assertThrows(
68+
MeiliSearchApiException.class,
69+
() -> client.createIndex(indexUid, this.primaryKey)
70+
);
71+
client.deleteIndex(index.getUid());
72+
}
73+
5674
/**
5775
* Test update Index PrimaryKey
5876
*/
@@ -107,7 +125,7 @@ public void testDeleteIndex() throws Exception {
107125
Index index = client.createIndex(indexUid);
108126
client.deleteIndex(index.getUid());
109127
assertThrows(
110-
Exception.class,
128+
MeiliSearchApiException.class,
111129
() -> client.getIndex(indexUid)
112130
);
113131
}

src/test/java/com/meilisearch/integration/DocumentsTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
import static org.junit.jupiter.api.Assertions.*;
1212

13+
import com.meilisearch.sdk.exceptions.MeiliSearchApiException;
14+
1315
@Tag("integration")
1416
public class DocumentsTest extends AbstractIT {
1517

@@ -180,7 +182,7 @@ public void testDeleteDocument() throws Exception {
180182
index.waitForPendingUpdate(updateInfo.getUpdateId());
181183

182184
assertThrows(
183-
Exception.class,
185+
MeiliSearchApiException.class,
184186
() -> index.getDocument(toDelete.getId())
185187
);
186188
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.meilisearch.integration;
2+
3+
import com.meilisearch.sdk.Index;
4+
import com.meilisearch.sdk.exceptions.MeiliSearchException;
5+
import com.meilisearch.sdk.exceptions.MeiliSearchApiException;
6+
import org.junit.jupiter.api.AfterAll;
7+
import org.junit.jupiter.api.BeforeEach;
8+
import org.junit.jupiter.api.Tag;
9+
import org.junit.jupiter.api.Test;
10+
11+
import static org.junit.jupiter.api.Assertions.*;
12+
13+
@Tag("integration")
14+
public class ExceptionsTest extends AbstractIT {
15+
16+
17+
@BeforeEach
18+
public void initialize() {
19+
this.setUp();
20+
}
21+
22+
@AfterAll
23+
static void cleanMeiliSearch() {
24+
cleanup();
25+
}
26+
27+
/**
28+
* Test MeiliSearchApiException serialization and getters
29+
*/
30+
@Test
31+
public void testErrorSerializeAndGetters() throws Exception {
32+
String errorMessage = "You must have an authorization token";
33+
String errorCode = "missing_authorization_header";
34+
String errorType = "authentication_error";
35+
String errorLink = "https://docs.meilisearch.com/errors#missing_authorization_header";
36+
try {
37+
throw new MeiliSearchApiException(
38+
"{"
39+
+ "\"message\":\"" + errorMessage + "\","
40+
+ "\"errorCode\":\"" + errorCode + "\","
41+
+ "\"errorType\":\"" + errorType + "\","
42+
+ "\"errorLink\":\"" + errorLink + "\""
43+
+ "}");
44+
} catch (MeiliSearchApiException e) {
45+
assertEquals(errorMessage, e.getMessage());
46+
assertEquals(errorCode, e.getErrorCode());
47+
assertEquals(errorType, e.getErrorType());
48+
assertEquals(errorLink, e.getErrorLink());
49+
}
50+
}
51+
52+
/**
53+
* Test MeiliSearchApiException is thrown on MeiliSearch bad request
54+
*/
55+
@Test
56+
public void testMeiliSearchApiExceptionBadRequest () throws Exception {
57+
String indexUid = "MeiliSearchApiExceptionBadRequest";
58+
Index index = client.createIndex(indexUid);
59+
assertThrows(
60+
MeiliSearchException.class,
61+
() -> client.createIndex(indexUid)
62+
);
63+
try {
64+
client.createIndex(indexUid);
65+
} catch (MeiliSearchApiException e) {
66+
assertEquals("index_already_exists", e.getErrorCode());
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)