Skip to content

Commit c373a53

Browse files
committed
fix for misleading error message
1 parent a1aba43 commit c373a53

6 files changed

Lines changed: 82 additions & 103 deletions

File tree

src/main/java/com/mindee/input/LocalResponse.java renamed to src/main/java/com/mindee/input/BaseLocalResponse.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@
2121
* A Mindee response saved locally.
2222
*/
2323
@Getter
24-
public abstract class LocalResponse {
24+
public abstract class BaseLocalResponse {
2525
protected final byte[] file;
2626

2727
/**
2828
* Load from an {@link InputStream}.
2929
*
3030
* @param input will be decoded as UTF-8.
3131
*/
32-
public LocalResponse(InputStream input) {
32+
public BaseLocalResponse(InputStream input) {
3333
this.file = this
3434
.getBytes(new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8)).lines());
3535
}
@@ -39,7 +39,10 @@ public LocalResponse(InputStream input) {
3939
*
4040
* @param input will be decoded as UTF-8.
4141
*/
42-
public LocalResponse(String input) {
42+
public BaseLocalResponse(String input) {
43+
if (input == null || input.isEmpty()) {
44+
throw new IllegalArgumentException("Input string cannot be empty or null.");
45+
}
4346
this.file = input.getBytes(StandardCharsets.UTF_8);
4447
}
4548

@@ -48,7 +51,7 @@ public LocalResponse(String input) {
4851
*
4952
* @param input will be decoded as UTF-8.
5053
*/
51-
public LocalResponse(File input) throws IOException {
54+
public BaseLocalResponse(File input) throws IOException {
5255
this.file = this.getBytes(Files.lines(input.toPath(), StandardCharsets.UTF_8));
5356
}
5457

@@ -57,7 +60,7 @@ public LocalResponse(File input) throws IOException {
5760
*
5861
* @param input will be decoded as UTF-8.
5962
*/
60-
public LocalResponse(Path input) throws IOException {
63+
public BaseLocalResponse(Path input) throws IOException {
6164
this.file = this.getBytes(Files.lines(input, StandardCharsets.UTF_8));
6265
}
6366

src/main/java/com/mindee/v1/MindeeClient.java

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
package com.mindee.v1;
22

3-
import com.fasterxml.jackson.databind.JavaType;
4-
import com.fasterxml.jackson.databind.ObjectMapper;
53
import com.mindee.AsyncPollingOptions;
64
import com.mindee.MindeeException;
75
import com.mindee.input.InputSourceUtils;
86
import com.mindee.input.LocalInputSource;
9-
import com.mindee.input.LocalResponse;
107
import com.mindee.input.PageOptions;
118
import com.mindee.pdf.PdfBoxApi;
129
import com.mindee.pdf.PdfOperation;
@@ -1071,28 +1068,4 @@ public <T extends GeneratedV1> AsyncPredictResponse<T> parseQueued(
10711068
) {
10721069
return this.mindeeApi.documentQueueGet(type, endpoint, jobId);
10731070
}
1074-
1075-
/**
1076-
* Load a local prediction.
1077-
* Typically used when wanting to load from a webhook callback.
1078-
* However, any kind of Mindee response may be loaded.
1079-
*
1080-
* @param <T> Type of inference.
1081-
* @param type Type of inference.
1082-
* @param localResponse A loaded local response.
1083-
* @return an instance of {@link AsyncPredictResponse}.
1084-
* @throws IOException Throws if the file can't be accessed.
1085-
*/
1086-
public <T extends Inference> AsyncPredictResponse<T> loadPrediction(
1087-
Class<T> type,
1088-
LocalResponse localResponse
1089-
) throws IOException {
1090-
ObjectMapper objectMapper = new ObjectMapper();
1091-
objectMapper.findAndRegisterModules();
1092-
JavaType parametricType = objectMapper
1093-
.getTypeFactory()
1094-
.constructParametricType(AsyncPredictResponse.class, type);
1095-
return objectMapper.readValue(localResponse.getFile(), parametricType);
1096-
}
1097-
10981071
}
Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.mindee.v1.input;
22

3+
import com.fasterxml.jackson.core.JacksonException;
34
import com.fasterxml.jackson.databind.ObjectMapper;
45
import com.mindee.MindeeException;
6+
import com.mindee.input.BaseLocalResponse;
57
import com.mindee.v1.parsing.common.AsyncPredictResponse;
68
import com.mindee.v1.parsing.common.Inference;
79
import com.mindee.v1.parsing.common.PredictResponse;
@@ -14,7 +16,7 @@
1416
/**
1517
* A Mindee response saved locally.
1618
*/
17-
public class LocalResponse extends com.mindee.input.LocalResponse {
19+
public class LocalResponse extends BaseLocalResponse {
1820

1921
public LocalResponse(InputStream input) {
2022
super(input);
@@ -32,52 +34,52 @@ public LocalResponse(Path input) throws IOException {
3234
super(input);
3335
}
3436

37+
private <P extends Inference, R> R deserialize(
38+
Class<R> responseClass,
39+
Class<P> productClass
40+
) throws IOException {
41+
var mapper = new ObjectMapper().findAndRegisterModules();
42+
var type = mapper.getTypeFactory().constructParametricType(responseClass, productClass);
43+
try {
44+
return mapper.readValue(this.file, type);
45+
} catch (Exception e) {
46+
if (e instanceof JacksonException) {
47+
throw new MindeeException("Invalid JSON payload.", e);
48+
}
49+
throw e;
50+
}
51+
}
52+
3553
/**
3654
* Deserialize this local JSON payload into a specific {@link AsyncPredictResponse}.
3755
* subtype: {@code InferenceResponse}, {@code JobResponse}.
3856
*
39-
* @param responseClass the concrete class to instantiate
57+
* @param productClass the concrete class to instantiate
4058
* @param <T> generic {@link Inference}
4159
* @return A {@link AsyncPredictResponse} instance.
4260
* @throws MindeeException if the payload cannot be deserialized into the requested type
4361
*/
4462
public <T extends Inference> AsyncPredictResponse<T> deserializeAsyncResponse(
45-
Class<T> responseClass
46-
) {
47-
var objectMapper = new ObjectMapper();
48-
objectMapper.findAndRegisterModules();
49-
var type = objectMapper
50-
.getTypeFactory()
51-
.constructParametricType(AsyncPredictResponse.class, responseClass);
52-
try {
53-
AsyncPredictResponse<T> response = objectMapper.readValue(this.file, type);
54-
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
55-
return response;
56-
} catch (Exception ex) {
57-
throw new MindeeException("Invalid class specified for deserialization.", ex);
58-
}
63+
Class<T> productClass
64+
) throws IOException {
65+
AsyncPredictResponse<T> response = deserialize(AsyncPredictResponse.class, productClass);
66+
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
67+
return response;
5968
}
6069

6170
/**
6271
* Deserialize this local JSON payload into a specific {@link PredictResponse}.
6372
*
64-
* @param responseClass the concrete class to instantiate
73+
* @param productClass the concrete class to instantiate
6574
* @param <T> generic {@link Inference}
6675
* @return A {@link PredictResponse} instance.
6776
* @throws MindeeException if the payload cannot be deserialized into the requested type
6877
*/
69-
public <T extends Inference> PredictResponse<T> deserializeSyncResponse(Class<T> responseClass) {
70-
var objectMapper = new ObjectMapper();
71-
objectMapper.findAndRegisterModules();
72-
var type = objectMapper
73-
.getTypeFactory()
74-
.constructParametricType(PredictResponse.class, responseClass);
75-
try {
76-
PredictResponse<T> response = objectMapper.readValue(this.file, type);
77-
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
78-
return response;
79-
} catch (Exception ex) {
80-
throw new MindeeException("Invalid class specified for deserialization.", ex);
81-
}
78+
public <T extends Inference> PredictResponse<T> deserializeSyncResponse(
79+
Class<T> productClass
80+
) throws IOException {
81+
PredictResponse<T> response = deserialize(PredictResponse.class, productClass);
82+
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
83+
return response;
8284
}
8385
}

src/main/java/com/mindee/v2/input/LocalResponse.java

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

33
import com.fasterxml.jackson.databind.ObjectMapper;
44
import com.mindee.MindeeException;
5+
import com.mindee.input.BaseLocalResponse;
56
import com.mindee.v2.parsing.CommonResponse;
67
import java.io.File;
78
import java.io.IOException;
@@ -12,7 +13,7 @@
1213
/**
1314
* A Mindee response saved locally.
1415
*/
15-
public class LocalResponse extends com.mindee.input.LocalResponse {
16+
public class LocalResponse extends BaseLocalResponse {
1617

1718
public LocalResponse(InputStream input) {
1819
super(input);
@@ -40,13 +41,13 @@ public LocalResponse(Path input) throws IOException {
4041
* @throws MindeeException if the payload cannot be deserialized into the requested type
4142
*/
4243
public <T extends CommonResponse> T deserializeResponse(Class<T> responseClass) {
43-
var mapper = new ObjectMapper();
44+
var mapper = new ObjectMapper().findAndRegisterModules();
4445
try {
4546
var response = mapper.readValue(this.file, responseClass);
4647
response.setRawResponse(new String(this.file, StandardCharsets.UTF_8));
4748
return response;
48-
} catch (Exception ex) {
49-
throw new MindeeException("Invalid class specified for deserialization.", ex);
49+
} catch (Exception e) {
50+
throw new MindeeException("Invalid JSON payload.", e);
5051
}
5152
}
5253
}

src/test/java/com/mindee/v1/MindeeClientTest.java

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
package com.mindee.v1;
22

3-
import static com.mindee.TestingUtilities.assertStringEqualsFile;
43
import static com.mindee.TestingUtilities.getResourcePath;
5-
import static com.mindee.TestingUtilities.getV1ResourcePathString;
64

75
import com.mindee.input.LocalInputSource;
86
import com.mindee.input.PageOptions;
97
import com.mindee.input.PageOptionsOperation;
108
import com.mindee.v1.clientOptions.PredictOptions;
11-
import com.mindee.v1.input.LocalResponse;
129
import com.mindee.v1.parsing.common.AsyncPredictResponse;
1310
import com.mindee.v1.parsing.common.Document;
1411
import com.mindee.v1.parsing.common.Job;
1512
import com.mindee.v1.parsing.common.PredictResponse;
16-
import com.mindee.v1.product.internationalid.InternationalIdV2;
1713
import com.mindee.v1.product.invoice.InvoiceV4;
18-
import java.io.File;
1914
import java.io.IOException;
2015
import java.net.URL;
2116
import java.nio.file.Files;
@@ -156,30 +151,4 @@ void givenAnAsyncUrl_whenEnqueued_shouldInvokeApiCorrectly() throws IOException
156151

157152
Assertions.assertEquals("someid", jobId);
158153
}
159-
160-
@Test
161-
void givenJsonInput_whenSync_shouldDeserializeCorrectly() throws IOException {
162-
File file = new File(getV1ResourcePathString("products/invoices/response_v4/complete.json"));
163-
LocalResponse localResponse = new LocalResponse(file);
164-
AsyncPredictResponse<InvoiceV4> predictResponse = new MindeeClient()
165-
.loadPrediction(InvoiceV4.class, localResponse);
166-
assertStringEqualsFile(
167-
predictResponse.getDocumentObj().toString(),
168-
getV1ResourcePathString("/products/invoices/response_v4/summary_full.rst")
169-
);
170-
}
171-
172-
@Test
173-
void givenJsonInput_whenAsync_shouldDeserializeCorrectly() throws IOException {
174-
File file = new File(
175-
getV1ResourcePathString("products/international_id/response_v2/complete.json")
176-
);
177-
LocalResponse localResponse = new LocalResponse(file);
178-
AsyncPredictResponse<InternationalIdV2> predictResponse = new MindeeClient()
179-
.loadPrediction(InternationalIdV2.class, localResponse);
180-
assertStringEqualsFile(
181-
predictResponse.getDocumentObj().toString(),
182-
getV1ResourcePathString("products/international_id/response_v2/summary_full.rst")
183-
);
184-
}
185154
}

src/test/java/com/mindee/v1/input/LocalResponseTest.java

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package com.mindee.v1.input;
22

3+
import static com.mindee.TestingUtilities.assertStringEqualsFile;
34
import static com.mindee.TestingUtilities.getV1ResourcePath;
5+
import static com.mindee.TestingUtilities.getV1ResourcePathString;
46

7+
import com.mindee.MindeeException;
58
import com.mindee.v1.product.internationalid.InternationalIdV2;
9+
import com.mindee.v1.product.invoice.InvoiceV4;
610
import java.io.File;
711
import java.io.IOException;
812
import java.nio.file.Files;
@@ -36,10 +40,6 @@ void loadDocument_withFile_mustReturnValidLocalResponse() throws IOException {
3640
);
3741
Assertions.assertEquals(this.signature, localResponse.getHmacSignature(this.secretKey));
3842
Assertions.assertTrue(localResponse.isValidHmacSignature(this.secretKey, this.signature));
39-
40-
var response = localResponse.deserializeAsyncResponse(InternationalIdV2.class);
41-
Assertions.assertNotNull(response);
42-
Assertions.assertNotNull(response.getDocumentObj());
4343
}
4444

4545
@Test
@@ -62,9 +62,40 @@ void loadDocument_withInputStream_mustReturnValidLocalResponse() throws IOExcept
6262
);
6363
Assertions.assertEquals(this.signature, localResponse.getHmacSignature(this.secretKey));
6464
Assertions.assertTrue(localResponse.isValidHmacSignature(this.secretKey, this.signature));
65+
}
66+
67+
@Test
68+
void givenJsonInput_whenSync_shouldDeserializeCorrectly() throws IOException {
69+
var localResponse = new LocalResponse(
70+
getV1ResourcePath("products/invoices/response_v4/complete.json")
71+
);
72+
var response = localResponse.deserializeSyncResponse(InvoiceV4.class);
73+
assertStringEqualsFile(
74+
response.getDocument().toString(),
75+
getV1ResourcePath("/products/invoices/response_v4/summary_full.rst")
76+
);
77+
}
6578

79+
@Test
80+
void givenJsonInput_whenAsync_shouldDeserializeCorrectly() throws IOException {
81+
var localResponse = new LocalResponse(
82+
getV1ResourcePath("products/international_id/response_v2/complete.json")
83+
);
6684
var response = localResponse.deserializeAsyncResponse(InternationalIdV2.class);
67-
Assertions.assertNotNull(response);
68-
Assertions.assertNotNull(response.getDocumentObj());
85+
assertStringEqualsFile(
86+
response.getDocumentObj().toString(),
87+
getV1ResourcePathString("products/international_id/response_v2/summary_full.rst")
88+
);
89+
}
90+
91+
@Test
92+
void givenInvalidJsonInput_shouldThrow() {
93+
var localResponse = new LocalResponse("{invalid json");
94+
var err = Assertions
95+
.assertThrows(
96+
MindeeException.class,
97+
() -> localResponse.deserializeSyncResponse(InvoiceV4.class)
98+
);
99+
Assertions.assertEquals("Invalid JSON payload.", err.getMessage());
69100
}
70101
}

0 commit comments

Comments
 (0)