fix: add support for reading DBRef type in Mongo plugin (#12670)
* DBRef fix with codec * Added code comments regarding custom codec implemented * Added Unit Test for Mongo DBRef Co-authored-by: Leo Thomas <leoweb2010@gmail.com> Co-authored-by: Sumit Kumar <sumit@appsmith.com>
This commit is contained in:
parent
db2310bef7
commit
f8cc2f5e54
|
|
@ -30,14 +30,25 @@ import com.external.plugins.utils.MongoErrorUtils;
|
|||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.mongodb.DBObjectCodecProvider;
|
||||
import com.mongodb.DBRefCodecProvider;
|
||||
import com.mongodb.MongoCommandException;
|
||||
import com.mongodb.MongoSocketWriteException;
|
||||
import com.mongodb.MongoTimeoutException;
|
||||
import com.mongodb.client.gridfs.codecs.GridFSFileCodecProvider;
|
||||
import com.mongodb.client.model.geojson.codecs.GeoJsonCodecProvider;
|
||||
import com.mongodb.reactivestreams.client.MongoClient;
|
||||
import com.mongodb.reactivestreams.client.MongoClients;
|
||||
import com.mongodb.reactivestreams.client.MongoDatabase;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bson.Document;
|
||||
import org.bson.codecs.BsonTypeClassMap;
|
||||
import org.bson.codecs.BsonValueCodecProvider;
|
||||
import org.bson.codecs.DocumentCodec;
|
||||
import org.bson.codecs.DocumentCodecProvider;
|
||||
import org.bson.codecs.ValueCodecProvider;
|
||||
import org.bson.codecs.configuration.CodecRegistries;
|
||||
import org.bson.codecs.configuration.CodecRegistry;
|
||||
import org.bson.conversions.Bson;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
|
@ -98,6 +109,7 @@ import static com.external.plugins.constants.FieldName.UPDATE_OPERATION;
|
|||
import static com.external.plugins.constants.FieldName.UPDATE_QUERY;
|
||||
import static com.external.plugins.utils.MongoPluginUtils.urlEncode;
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.apache.logging.log4j.util.Strings.isBlank;
|
||||
|
||||
public class MongoPlugin extends BasePlugin {
|
||||
|
|
@ -178,7 +190,7 @@ public class MongoPlugin extends BasePlugin {
|
|||
|
||||
private static final Integer MONGO_COMMAND_EXCEPTION_UNAUTHORIZED_ERROR_CODE = 13;
|
||||
|
||||
private static final Set<String> bsonFields = new HashSet<>(Arrays.asList(
|
||||
private static final Set<String> bsonFields = new HashSet<>(asList(
|
||||
AGGREGATE_PIPELINES,
|
||||
COUNT_QUERY,
|
||||
DELETE_QUERY,
|
||||
|
|
@ -193,6 +205,18 @@ public class MongoPlugin extends BasePlugin {
|
|||
|
||||
private static final MongoErrorUtils mongoErrorUtils = MongoErrorUtils.getInstance();
|
||||
|
||||
private static final CodecRegistry DEFAULT_REGISTRY = CodecRegistries.fromProviders(
|
||||
asList(new ValueCodecProvider(),
|
||||
new BsonValueCodecProvider(),
|
||||
new DocumentCodecProvider(),
|
||||
new DBRefCodecProvider(),
|
||||
new DBObjectCodecProvider(),
|
||||
new BsonValueCodecProvider(),
|
||||
new GeoJsonCodecProvider(),
|
||||
new GridFSFileCodecProvider()));
|
||||
|
||||
private static final BsonTypeClassMap DEFAULT_BSON_TYPE_CLASS_MAP = new org.bson.codecs.BsonTypeClassMap();
|
||||
|
||||
public MongoPlugin(PluginWrapper wrapper) {
|
||||
super(wrapper);
|
||||
}
|
||||
|
|
@ -332,7 +356,17 @@ public class MongoPlugin extends BasePlugin {
|
|||
)
|
||||
.flatMap(mongoOutput -> {
|
||||
try {
|
||||
JSONObject outputJson = new JSONObject(mongoOutput.toJson());
|
||||
/*
|
||||
* Added Custom codec for JSON conversion since MongoDB Reactive API does not support
|
||||
* processing of DbRef Object.
|
||||
* https://github.com/spring-projects/spring-data-mongodb/issues/3015 : Mark Paluch commented
|
||||
*/
|
||||
DocumentCodec documentCodec = new DocumentCodec(
|
||||
DEFAULT_REGISTRY,
|
||||
DEFAULT_BSON_TYPE_CLASS_MAP
|
||||
);
|
||||
|
||||
JSONObject outputJson = new JSONObject(mongoOutput.toJson(documentCodec));
|
||||
|
||||
//The output json contains the key "ok". This is the status of the command
|
||||
BigInteger status = outputJson.getBigInteger("ok");
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ import com.appsmith.external.models.ParsedDataType;
|
|||
import com.appsmith.external.models.Property;
|
||||
import com.appsmith.external.models.RequestParamDTO;
|
||||
import com.appsmith.external.models.SSLDetails;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.mongodb.MongoCommandException;
|
||||
|
|
@ -26,6 +28,7 @@ import com.mongodb.reactivestreams.client.MongoClient;
|
|||
import com.mongodb.reactivestreams.client.MongoClients;
|
||||
import com.mongodb.reactivestreams.client.MongoCollection;
|
||||
import com.mongodb.reactivestreams.client.MongoDatabase;
|
||||
import com.mongodb.DBRef;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.BSONTimestamp;
|
||||
import org.bson.types.Decimal128;
|
||||
|
|
@ -135,8 +138,25 @@ public class MongoPluginTest {
|
|||
)),
|
||||
new Document(Map.of("name", "Kierra Gentry", "gender", "F", "age", 40))
|
||||
))).block();
|
||||
}
|
||||
|
||||
|
||||
final MongoCollection<Document> addressCollection = mongoClient.getDatabase("test")
|
||||
.getCollection("address");
|
||||
Mono.from(addressCollection.insertMany(List.of(
|
||||
new Document(Map.of(
|
||||
"user", new DBRef("test", "users", "1"),
|
||||
"street", "First Street",
|
||||
"city", "Line One",
|
||||
"state", "UP"
|
||||
)),
|
||||
new Document(Map.of(
|
||||
"user", new DBRef("AAA", "BBB", "2000"),
|
||||
"street", "Second Street",
|
||||
"city", "Line Two",
|
||||
"state", "UP"
|
||||
))
|
||||
))).block();
|
||||
}
|
||||
return Mono.empty();
|
||||
}).block();
|
||||
}
|
||||
|
|
@ -249,6 +269,55 @@ public class MongoPluginTest {
|
|||
.verifyComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for DBRef after codec implementation
|
||||
*/
|
||||
@Test
|
||||
public void testExecuteQueryDBRef() {
|
||||
DatasourceConfiguration dsConfig = createDatasourceConfiguration();
|
||||
Mono<MongoClient> dsConnectionMono = pluginExecutor.datasourceCreate(dsConfig);
|
||||
|
||||
ActionConfiguration actionConfiguration = new ActionConfiguration();
|
||||
|
||||
Map<String, Object> configMap = new HashMap<>();
|
||||
setValueSafelyInFormData(configMap, SMART_SUBSTITUTION, Boolean.TRUE);
|
||||
setValueSafelyInFormData(configMap, COMMAND, "RAW");
|
||||
setValueSafelyInFormData(configMap, BODY, "{\n" +
|
||||
" find: \"address\",\n" +
|
||||
" limit: 10,\n" +
|
||||
" }");
|
||||
actionConfiguration.setFormData(configMap);
|
||||
|
||||
Mono<Object> executeMono = dsConnectionMono.flatMap(conn -> pluginExecutor.executeParameterized(conn, new ExecuteActionDTO(), dsConfig, actionConfiguration));
|
||||
|
||||
StepVerifier.create(executeMono)
|
||||
.assertNext(obj -> {
|
||||
ActionExecutionResult result = (ActionExecutionResult) obj;
|
||||
assertNotNull(result);
|
||||
assertTrue(result.getIsExecutionSuccess());
|
||||
assertNotNull(result.getBody());
|
||||
|
||||
assertEquals(2, ((ArrayNode) result.getBody()).size());
|
||||
|
||||
/*
|
||||
* Provided Input : new DBRef("test", "users", "1")
|
||||
* To test if we are getting the expected output after external codec implementation.
|
||||
* Note: when the codec is removed from the MongoDBPlugin, this is found failing
|
||||
*/
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String expectedOutputJsonString = "{\"$db\":\"test\",\"$ref\":\"users\",\"$id\":\"1\"}";
|
||||
JsonNode outputNode = mapper.readTree(expectedOutputJsonString);
|
||||
assertEquals(outputNode, (((ArrayNode) result.getBody()).findValue("user")));
|
||||
} catch (JsonProcessingException e) {
|
||||
assert false;
|
||||
}
|
||||
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExecuteReadQuery() {
|
||||
DatasourceConfiguration dsConfig = createDatasourceConfiguration();
|
||||
|
|
@ -475,8 +544,13 @@ public class MongoPluginTest {
|
|||
|
||||
StepVerifier.create(structureMono)
|
||||
.assertNext(structure -> {
|
||||
//Sort the Tables since one more table is added and to maintain sequence
|
||||
structure.getTables().sort(
|
||||
(DatasourceStructure.Table t1, DatasourceStructure.Table t2)
|
||||
->t2.getName().compareTo(t1.getName())
|
||||
);
|
||||
assertNotNull(structure);
|
||||
assertEquals(1, structure.getTables().size());
|
||||
assertEquals(2, structure.getTables().size());
|
||||
|
||||
final DatasourceStructure.Table usersTable = structure.getTables().get(0);
|
||||
assertEquals("users", usersTable.getName());
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user