Skip to content

Commit

Permalink
Fix: Prevent multiple cursor creation in KintoneClient
Browse files Browse the repository at this point in the history
- Ensure KintoneClient#createCursor throws a RuntimeException if a cursor already exists to prevent creating a new cursor without deleting the previous one.
- Defined error message as a private static final field.
- Added a test case in TestKintoneClient to verify that an exception is thrown when trying to create a cursor while one already exists.
  • Loading branch information
kentoyoshida committed Jul 25, 2024
1 parent 4eebddc commit c187825
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/main/java/org/embulk/input/kintone/KintoneClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class KintoneClient implements AutoCloseable
{
private final Logger logger = LoggerFactory.getLogger(KintoneClient.class);
private static final int FETCH_SIZE = 500;
private static final String CURSOR_ALREADY_EXISTS_ERROR = "Cursor already exists: KintoneClient can only generate one cursor per instance.";
private RecordClient recordClient;
private AppClient appClient;
private String cursorId;
Expand Down Expand Up @@ -102,6 +103,9 @@ public GetRecordsByCursorResponseBody getRecordsByCursor()

public void createCursor(final PluginTask task, final Schema schema)
{
if (this.cursorId != null) {
throw new RuntimeException(CURSOR_ALREADY_EXISTS_ERROR);
}
ArrayList<String> fields = new ArrayList<>();
for (Column c : schema.getColumns()) {
fields.add(c.getName());
Expand Down
41 changes: 41 additions & 0 deletions src/test/java/org/embulk/input/kintone/TestKintoneClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@
import org.embulk.config.ConfigException;
import org.embulk.config.ConfigSource;
import org.embulk.spi.InputPlugin;
import org.embulk.spi.Schema;
import org.embulk.test.TestingEmbulk;
import org.junit.Rule;
import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -166,4 +170,41 @@ public void checkGetFieldCodes()
assertEquals(1, client.getFieldCodes(task, FieldType.SUBTABLE).size());
assertTrue(client.getFieldCodes(task, FieldType.SUBTABLE).contains("subtable2"));
}

@Test
public void testCreateCursorThrowsExceptionWhenCursorAlreadyExists()
{
config = loadYamlResource(embulk);
PluginTask task = configMapper.map(config, PluginTask.class);
Schema schema = mock(Schema.class);

KintoneClient client = new KintoneClient(appClient);

try {
Field cursorIdField = KintoneClient.class.getDeclaredField("cursorId");
cursorIdField.setAccessible(true);
cursorIdField.set(client, "existingCursorId");

Field cursorAlreadyExistsErrorField = KintoneClient.class.getDeclaredField("CURSOR_ALREADY_EXISTS_ERROR");
cursorAlreadyExistsErrorField.setAccessible(true);
String cursorAlreadyExistsErrorMessage = (String) cursorAlreadyExistsErrorField.get(null);

Method createCursorMethod = KintoneClient.class.getDeclaredMethod("createCursor", PluginTask.class, Schema.class);
createCursorMethod.setAccessible(true);

Exception exception = assertThrows(RuntimeException.class, () -> {
try {
createCursorMethod.invoke(client, task, schema);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
});

assertEquals(cursorAlreadyExistsErrorMessage, exception.getMessage());
}
catch (Exception e) {
throw new RuntimeException("Reflection error", e);
}
}
}

0 comments on commit c187825

Please sign in to comment.