Skip to content

Commit

Permalink
Improve Java to Ballerina call logic (#2135)
Browse files Browse the repository at this point in the history
  • Loading branch information
warunalakshitha authored Dec 19, 2024
1 parent 3539776 commit 73ddff7
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@
import io.ballerina.runtime.api.values.BString;
import io.ballerina.runtime.api.values.BTypedesc;

import java.util.concurrent.CompletableFuture;

import static io.ballerina.stdlib.graphql.runtime.utils.ModuleUtils.getResult;

/**
* This class is used to execute a GraphQL document using the Ballerina GraphQL client.
*/
Expand Down Expand Up @@ -67,15 +63,11 @@ private static Object invokeClientMethod(Environment env, BObject client, BStrin

private static Object invokeClientMethod(Environment env, BObject client, String methodName, Object[] paramFeed) {
return env.yieldAndRun(() -> {
CompletableFuture<Object> balFuture = new CompletableFuture<>();
QueryExecutorCallback executorCallback = new QueryExecutorCallback(balFuture);
try {
Object result = env.getRuntime().callMethod(client, methodName, null, paramFeed);
executorCallback.notifySuccess(result);
return env.getRuntime().callMethod(client, methodName, null, paramFeed);
} catch (BError bError) {
executorCallback.notifyFailure(bError);
return bError;
}
return getResult(balFuture);
});
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

import static io.ballerina.runtime.api.types.TypeTags.INTERSECTION_TAG;
import static io.ballerina.stdlib.graphql.runtime.engine.EngineUtils.ARGUMENTS_FIELD;
Expand All @@ -64,6 +63,7 @@
import static io.ballerina.stdlib.graphql.runtime.engine.EngineUtils.isEnum;
import static io.ballerina.stdlib.graphql.runtime.engine.EngineUtils.isIgnoreType;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.INTERNAL_NODE;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.handleFailureAndExit;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.isContext;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.isField;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.isFileUpload;
Expand Down Expand Up @@ -540,16 +540,13 @@ private boolean isRepresentationArgument(Type type) {

private void addConstraintValidationErrors(Environment environment, BArray errors) {
environment.yieldAndRun(() -> {
CompletableFuture<Object> future = new CompletableFuture<>();
ExecutionCallback executionCallback = new ExecutionCallback(future);
BObject fieldNode = this.field.getObjectValue(INTERNAL_NODE);
Object[] arguments = {errors, fieldNode};
try {
Object result = environment.getRuntime()
.callMethod(this.responseGenerator, ADD_CONSTRAINT_ERRORS_METHOD, null, arguments);
executionCallback.notifySuccess(result);
return environment.getRuntime().callMethod(this.responseGenerator, ADD_CONSTRAINT_ERRORS_METHOD,
null, arguments);
} catch (BError bError) {
executionCallback.notifyFailure(bError);
handleFailureAndExit(bError);
}
return null;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
import io.ballerina.runtime.api.values.BObject;
import io.ballerina.runtime.api.values.BTypedesc;

import java.util.concurrent.CompletableFuture;

import static io.ballerina.stdlib.graphql.runtime.utils.ModuleUtils.getResult;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.handleFailureAndExit;

/**
* This class provides native implementations of the Ballerina DataLoader class.
Expand All @@ -38,17 +36,13 @@ private DataLoader() {

public static Object get(Environment env, BObject dataLoader, Object key, BTypedesc typedesc) {
return env.yieldAndRun(() -> {
CompletableFuture<Object> balFuture = new CompletableFuture<>();
Object[] paramFeed = getProcessGetMethodParams(key, typedesc);
ExecutionCallback executionCallback = new ExecutionCallback(balFuture);
try {
Object result = env.getRuntime().callMethod(dataLoader, DATA_LOADER_PROCESSES_GET_METHOD_NAME, null,
paramFeed);
executionCallback.notifySuccess(result);
return env.getRuntime().callMethod(dataLoader, DATA_LOADER_PROCESSES_GET_METHOD_NAME, null, paramFeed);
} catch (BError bError) {
executionCallback.notifyFailure(bError);
handleFailureAndExit(bError);
}
return getResult(balFuture);
return null;
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;

import static io.ballerina.runtime.observability.ObservabilityConstants.KEY_OBSERVER_CONTEXT;
import static io.ballerina.stdlib.graphql.commons.utils.TypeUtils.removeEscapeCharacter;
Expand All @@ -64,10 +63,10 @@
import static io.ballerina.stdlib.graphql.runtime.engine.EngineUtils.SUBSCRIBE_ACCESSOR;
import static io.ballerina.stdlib.graphql.runtime.engine.EngineUtils.isPathsMatching;
import static io.ballerina.stdlib.graphql.runtime.utils.ModuleUtils.getModule;
import static io.ballerina.stdlib.graphql.runtime.utils.ModuleUtils.getResult;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.ERROR_TYPE;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.INTERNAL_NODE;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.createError;
import static io.ballerina.stdlib.graphql.runtime.utils.Utils.handleFailureAndExit;

/**
* This handles Ballerina GraphQL Engine.
Expand Down Expand Up @@ -119,30 +118,27 @@ public static Object executeSubscriptionResource(Environment environment, BObjec
fieldName.getValue().equals(removeEscapeCharacter(resourceMethod.getResourcePath()[0]))) {
ArgumentHandler argumentHandler =
new ArgumentHandler(resourceMethod, context, fieldObject, responseGenerator, validation);
return getResultObject(environment, context, service, resourceMethod.getName(), argumentHandler);
return getResultObject(environment, service, resourceMethod.getName(), argumentHandler);
}
}
return null;
}

private static Object getResultObject(Environment environment, BObject context, BObject service,
String methodName, ArgumentHandler argumentHandler) {
private static Object getResultObject(Environment environment, BObject service, String methodName,
ArgumentHandler argumentHandler) {
try {
argumentHandler.validateInputConstraint(environment);
} catch (ConstraintValidationException e) {
return null;
}
return environment.yieldAndRun(() -> {
CompletableFuture<Object> subscriptionFutureResult = new CompletableFuture<>();
ExecutionCallback executionCallback = new ExecutionCallback(subscriptionFutureResult);
Object[] args = argumentHandler.getArguments();
try {
Object result = callResourceMethod(environment.getRuntime(), service, methodName, args);
executionCallback.notifySuccess(result);
return callResourceMethod(environment.getRuntime(), service, methodName, args);
} catch (BError bError) {
executionCallback.notifyFailure(bError);
handleFailureAndExit(bError);
}
return getResult(subscriptionFutureResult);
return null;
});
}

Expand All @@ -158,7 +154,7 @@ public static Object executeQueryResource(Environment environment, BObject conte
}
ArgumentHandler argumentHandler =
new ArgumentHandler(resourceMethod, context, fieldObject, responseGenerator, validation);
return getResultObject(environment, context, service, resourceMethod.getName(), argumentHandler);
return getResultObject(environment, service, resourceMethod.getName(), argumentHandler);
}

public static Object executeMutationMethod(Environment environment, BObject context, BObject service,
Expand All @@ -169,7 +165,7 @@ public static Object executeMutationMethod(Environment environment, BObject cont
if (remoteMethod.getName().equals(fieldName)) {
ArgumentHandler argumentHandler =
new ArgumentHandler(remoteMethod, context, fieldObject, responseGenerator, validation);
return getResultObject(environment, context, service, remoteMethod.getName(), argumentHandler);
return getResultObject(environment, service, remoteMethod.getName(), argumentHandler);
}
}
return null;
Expand All @@ -183,17 +179,13 @@ public static Object executeInterceptor(Environment environment, BObject interce
return null;
}
return environment.yieldAndRun(() -> {
CompletableFuture<Object> future = new CompletableFuture<>();
ExecutionCallback executionCallback = new ExecutionCallback(future);
Object[] arguments = getInterceptorArguments(context, field);
try {
Object result = callResourceMethod(environment.getRuntime(), interceptor, remoteMethod.getName(),
arguments);
executionCallback.notifySuccess(result);
return callResourceMethod(environment.getRuntime(), interceptor, remoteMethod.getName(), arguments);
} catch (BError bError) {
executionCallback.notifyFailure(bError);
handleFailureAndExit(bError);
}
return getResult(future);
return null;
});
}

Expand Down Expand Up @@ -283,16 +275,12 @@ public static boolean hasPrefetchMethod(BObject serviceObject, BString prefetchM
public static void executePrefetchMethod(Environment environment, BObject context, BObject service,
MethodType resourceMethod, BObject fieldObject) {
environment.yieldAndRun(() -> {
CompletableFuture<Object> future = new CompletableFuture<>();
ExecutionCallback executionCallback = new ExecutionCallback(future);
ArgumentHandler argumentHandler = new ArgumentHandler(resourceMethod, context, fieldObject, null, false);
Object[] arguments = argumentHandler.getArguments();
try {
Object result = callResourceMethod(environment.getRuntime(), service, resourceMethod.getName(),
arguments);
executionCallback.notifySuccess(result);
return callResourceMethod(environment.getRuntime(), service, resourceMethod.getName(), arguments);
} catch (BError bError) {
executionCallback.notifyFailure(bError);
handleFailureAndExit(bError);
}
return null;
});
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@

import io.ballerina.runtime.api.Environment;
import io.ballerina.runtime.api.Module;
import io.ballerina.runtime.api.creators.ErrorCreator;
import io.ballerina.runtime.api.values.BError;

import java.util.concurrent.CompletableFuture;

/**
* This class includes the utility functions related to Ballerina GraphQL module.
Expand All @@ -44,17 +40,4 @@ public static void setModule(Environment environment) {
public static Module getModule() {
return module;
}

public static Object getResult(CompletableFuture<Object> balFuture) {
try {
return balFuture.get();
} catch (BError error) {
throw error;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw ErrorCreator.createError(e);
} catch (Throwable throwable) {
throw ErrorCreator.createError(throwable);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,13 @@ private static boolean hasExpectedModuleName(Type type, String expectedModuleNam
public static BString getHashCode(BObject object) {
return StringUtils.fromString(Integer.toString(object.hashCode()));
}

public static void handleFailureAndExit(BError bError) {
bError.printStackTrace();
// Service level `panic` is captured in this method.
// Since, `panic` is due to a critical application bug or resource exhaustion we need to exit the
// application.
// Please refer: https://github.com/ballerina-platform/ballerina-standard-library/issues/2714
System.exit(1);
}
}
4 changes: 2 additions & 2 deletions spotbugs-exclude.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
</Match>
<Match>
<And>
<Class name="io.ballerina.stdlib.graphql.runtime.engine.ExecutionCallback" />
<Method name = "notifyFailure" />
<Class name="io.ballerina.stdlib.graphql.runtime.utils.Utils" />
<Method name = "handleFailureAndExit" />
<Bug pattern="DM_EXIT" />
</And>
</Match>
Expand Down

0 comments on commit 73ddff7

Please sign in to comment.