diff --git a/.github/workflows/build-timestamped-master.yml b/.github/workflows/build-timestamped-master.yml index 7be9403..a66b465 100644 --- a/.github/workflows/build-timestamped-master.yml +++ b/.github/workflows/build-timestamped-master.yml @@ -13,11 +13,11 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: 17.0.7 + java-version: 21 - name: Change to Timestamped Version run: | startTime=$(TZ="Asia/Kolkata" date +'%Y%m%d-%H%M00') diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 914474b..2041f80 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -11,11 +11,11 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: 17.0.7 + java-version: 21 - name: Build with Gradle env: packageUser: ${{ github.actor }} diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 4978731..412874e 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -9,11 +9,11 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: 17.0.7 + java-version: 21 - name: Build with Gradle env: packageUser: ${{ github.actor }} @@ -29,11 +29,11 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: 17.0.7 + java-version: 21 - name: Build with Gradle env: packageUser: ${{ github.actor }} @@ -49,11 +49,11 @@ jobs: steps: - name: Checkout Repository uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: 17.0.7 + java-version: 21 - name: Build with Gradle env: packageUser: ${{ github.actor }} diff --git a/.github/workflows/trivy-scan.yml b/.github/workflows/trivy-scan.yml index 9ca642a..42c2b13 100644 --- a/.github/workflows/trivy-scan.yml +++ b/.github/workflows/trivy-scan.yml @@ -11,11 +11,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v3 with: distribution: 'adopt' - java-version: 17.0.7 + java-version: 21 - name: Build with Gradle env: packageUser: ${{ github.actor }} diff --git a/README.md b/README.md index 884bb2d..c4b764d 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This module contains internal configurations and initializations for Ballerina o ### Set Up the prerequisites -1. Download and install Java SE Development Kit (JDK) version 17 (from one of the following locations). +1. Download and install Java SE Development Kit (JDK) version 21 (from one of the following locations). * [Oracle](https://www.oracle.com/java/technologies/downloads/) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 20d3601..66bf798 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -4,8 +4,8 @@ name = "observe" version = "1.3.0" distribution = "2201.10.0" -[platform.java17] +[platform.java21] graalvmCompatible = true -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "../native/build/libs/observe-internal-native-1.3.0.jar" diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index bf293d5..c2c9ac9 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -4,8 +4,8 @@ name = "observe" version = "@toml.version@" distribution = "2201.10.0" -[platform.java17] +[platform.java21] graalvmCompatible = true -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "../native/build/libs/observe-internal-native-@project.version@.jar" diff --git a/build-config/resources/testobserve/Ballerina.toml b/build-config/resources/testobserve/Ballerina.toml index edac22b..3d50a76 100644 --- a/build-config/resources/testobserve/Ballerina.toml +++ b/build-config/resources/testobserve/Ballerina.toml @@ -3,5 +3,5 @@ org = "ballerina" name = "testobserve" version = "0.0.0" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "../native/build/libs/testobserve-native-@project.version@-all.jar" diff --git a/build.gradle b/build.gradle index 3ce0e04..4883de6 100644 --- a/build.gradle +++ b/build.gradle @@ -16,10 +16,10 @@ */ plugins { - id "com.github.spotbugs" version "5.0.14" - id "com.github.johnrengelman.shadow" version "8.1.1" - id "de.undercouch.download" version "5.4.0" - id "net.researchgate.release" version "2.8.0" + id "com.github.spotbugs" version "${githubSpotbugsVersion}" + id "com.github.johnrengelman.shadow" version "${githubJohnrengelmanShadowVersion}" + id "de.undercouch.download" version "${underCouchDownloadVersion}" + id "net.researchgate.release" version "${researchgateReleaseVersion}" } allprojects { diff --git a/gradle.properties b/gradle.properties index 5839fa6..432a005 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,7 +16,11 @@ org.gradle.caching=true group=io.ballerina version=1.3.1-SNAPSHOT -ballerinaLangVersion=2201.10.0 +ballerinaLangVersion=2201.11.0-20241117-133400-a3054b77 +githubSpotbugsVersion=6.0.18 +githubJohnrengelmanShadowVersion=8.1.1 +underCouchDownloadVersion=5.4.0 +researchgateReleaseVersion=2.8.0 ballerinaTomlParserVersion=1.2.2 ballerinaGradlePluginVersion=2.0.1 puppycrawlCheckstyleVersion=10.12.0 @@ -24,7 +28,7 @@ openTelemetryVersion=1.7.0 nettyCodecVersion=4.1.100.Final gsonVersion=2.10.1 -observeVersion=1.3.0 +observeVersion=1.4.0-20241113-092000-b83ae74 # Test Dependency Versions testngVersion=7.6.1 diff --git a/native/build.gradle b/native/build.gradle index fa73007..94cf213 100644 --- a/native/build.gradle +++ b/native/build.gradle @@ -48,8 +48,11 @@ tasks.withType(Checkstyle) { checkstyleMain.dependsOn(":checkstyle:downloadCheckstyleRuleFiles") spotbugsMain { - effort "max" - reportLevel "low" + def classLoader = plugins["com.github.spotbugs"].class.classLoader + def SpotBugsConfidence = classLoader.findLoadedClass("com.github.spotbugs.snom.Confidence") + def SpotBugsEffort = classLoader.findLoadedClass("com.github.spotbugs.snom.Effort") + effort = SpotBugsEffort.MAX + reportLevel = SpotBugsConfidence.LOW reportsDir = file("$project.buildDir/reports/spotbugs") reports { html.enabled true diff --git a/testobserve/ballerina/Ballerina.toml b/testobserve/ballerina/Ballerina.toml index bd1e941..ca2c9e4 100644 --- a/testobserve/ballerina/Ballerina.toml +++ b/testobserve/ballerina/Ballerina.toml @@ -3,5 +3,5 @@ org = "ballerina" name = "testobserve" version = "0.0.0" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "../native/build/libs/testobserve-native-1.3.0-SNAPSHOT-all.jar" diff --git a/testobserve/native/build.gradle b/testobserve/native/build.gradle index 00e4628..f1b895e 100644 --- a/testobserve/native/build.gradle +++ b/testobserve/native/build.gradle @@ -55,8 +55,11 @@ tasks.withType(Checkstyle) { checkstyleMain.dependsOn(":checkstyle:downloadCheckstyleRuleFiles") spotbugsMain { - effort "max" - reportLevel "low" + def classLoader = plugins["com.github.spotbugs"].class.classLoader + def SpotBugsConfidence = classLoader.findLoadedClass("com.github.spotbugs.snom.Confidence") + def SpotBugsEffort = classLoader.findLoadedClass("com.github.spotbugs.snom.Effort") + effort = SpotBugsEffort.MAX + reportLevel = SpotBugsConfidence.LOW reportsDir = file("$project.buildDir/reports/spotbugs") reports { html.enabled true diff --git a/testobserve/native/spotbugs-exclude.xml b/testobserve/native/spotbugs-exclude.xml index c7809b9..d4cb84b 100644 --- a/testobserve/native/spotbugs-exclude.xml +++ b/testobserve/native/spotbugs-exclude.xml @@ -16,14 +16,28 @@ ~ under the License. --> + + + + - + + + + + + + + + + + diff --git a/testobserve/native/src/main/java/org/ballerina/testobserve/NativeUtils.java b/testobserve/native/src/main/java/org/ballerina/testobserve/NativeUtils.java index 8870da3..ce140b0 100644 --- a/testobserve/native/src/main/java/org/ballerina/testobserve/NativeUtils.java +++ b/testobserve/native/src/main/java/org/ballerina/testobserve/NativeUtils.java @@ -19,11 +19,11 @@ package org.ballerina.testobserve; import io.ballerina.runtime.api.Environment; -import io.ballerina.runtime.api.Future; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.utils.StringUtils; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; /** * Native functions for the utilities in testobserve module. @@ -34,7 +34,13 @@ public class NativeUtils { private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(CORE_THREAD_POOL_SIZE); public static void sleep(Environment env, long delayMillis) { - Future balFuture = env.markAsync(); - executor.schedule(() -> balFuture.complete(null), delayMillis, TimeUnit.MILLISECONDS); + env.yieldAndRun(() -> { + try { + Thread.sleep(delayMillis); + return null; + } catch (InterruptedException e) { + throw ErrorCreator.createError(StringUtils.fromString("error occurred during sleep"), e); + } + }); } } diff --git a/testobserve/native/src/main/java/org/ballerina/testobserve/listenerendpoint/Endpoint.java b/testobserve/native/src/main/java/org/ballerina/testobserve/listenerendpoint/Endpoint.java index faef3a5..c0a6016 100644 --- a/testobserve/native/src/main/java/org/ballerina/testobserve/listenerendpoint/Endpoint.java +++ b/testobserve/native/src/main/java/org/ballerina/testobserve/listenerendpoint/Endpoint.java @@ -34,7 +34,7 @@ public class Endpoint { public static void initEndpoint(Environment env, BObject listenerEndpoint, int port) { - WebServer webServer = new WebServer(port, env.getRuntime()); + WebServer webServer = new WebServer(port, env); listenerEndpoint.addNativeData(WEB_SERVER_NATIVE_DATA_KEY, webServer); Utils.logInfo("Initialized Web Server with port " + port); } diff --git a/testobserve/native/src/main/java/org/ballerina/testobserve/listenerendpoint/WebServer.java b/testobserve/native/src/main/java/org/ballerina/testobserve/listenerendpoint/WebServer.java index 13b1401..ab2e209 100644 --- a/testobserve/native/src/main/java/org/ballerina/testobserve/listenerendpoint/WebServer.java +++ b/testobserve/native/src/main/java/org/ballerina/testobserve/listenerendpoint/WebServer.java @@ -18,10 +18,11 @@ package org.ballerina.testobserve.listenerendpoint; -import io.ballerina.runtime.api.Runtime; -import io.ballerina.runtime.api.async.Callback; -import io.ballerina.runtime.api.async.StrandMetadata; +import io.ballerina.runtime.api.Environment; +import io.ballerina.runtime.api.concurrent.StrandMetadata; +import io.ballerina.runtime.api.creators.ErrorCreator; import io.ballerina.runtime.api.creators.ValueCreator; +import io.ballerina.runtime.api.types.ObjectType; import io.ballerina.runtime.api.types.ResourceMethodType; import io.ballerina.runtime.api.types.ServiceType; import io.ballerina.runtime.api.utils.StringUtils; @@ -84,12 +85,12 @@ public class WebServer { private final Map resourceMap = new ConcurrentHashMap<>(); private final int port; private final EventLoopGroup loopGroup; - private final Runtime runtime; + private final Environment env; - public WebServer(int port, Runtime runtime) { + public WebServer(int port, Environment env) { this.port = port; this.loopGroup = new NioEventLoopGroup(); - this.runtime = runtime; + this.env = env; } /** @@ -148,7 +149,7 @@ protected void initChannel(SocketChannel channel) { pipeline.addLast("decoder", new HttpRequestDecoder(4096, 8192, 8192, false)); pipeline.addLast("aggregator", new HttpObjectAggregator(100 * 1024 * 1024)); pipeline.addLast("encoder", new HttpResponseEncoder()); - pipeline.addLast("handler", new WebServerInboundHandler(runtime, resourceMap)); + pipeline.addLast("handler", new WebServerInboundHandler(env, resourceMap)); } }) .bind(this.port) @@ -187,11 +188,11 @@ public void shutdownNow() throws InterruptedException { * Inbound message handler of the Web Server. */ public static class WebServerInboundHandler extends SimpleChannelInboundHandler { - private final Runtime runtime; + private final Environment env; private final Map resourceMap; - public WebServerInboundHandler(Runtime runtime, Map resourceMap) { - this.runtime = runtime; + public WebServerInboundHandler(Environment env, Map resourceMap) { + this.env = env; this.resourceMap = resourceMap; } @@ -202,10 +203,9 @@ public void channelReadComplete(ChannelHandlerContext ctx) { @Override protected void channelRead0(ChannelHandlerContext ctx, Object o) { - if (!(o instanceof FullHttpRequest)) { + if (!(o instanceof FullHttpRequest request)) { return; } - final FullHttpRequest request = (FullHttpRequest) o; String httpMethod = request.method().name(); String resourcePath = Utils.normalizeResourcePath(request.uri()); String resourceMapKey = generateResourceMapKey(httpMethod, resourcePath); @@ -222,15 +222,13 @@ protected void channelRead0(ChannelHandlerContext ctx, Object o) { BObject serviceObject = resource.getServiceObject(); String resourceFunctionName = resource.getResourceFunctionName(); int paramCount = resource.getParamTypes().length; - Object[] args = new Object[paramCount * 2]; + Object[] args = new Object[paramCount]; if (paramCount >= 1) { args[0] = callerObject; - args[1] = true; } if (paramCount >= 2 && request.method() == HttpMethod.POST) { String bodyContent = request.content().toString(StandardCharsets.UTF_8); - args[2] = StringUtils.fromString(bodyContent); - args[3] = true; + args[1] = StringUtils.fromString(bodyContent); } ObserverContext observerContext = new ObserverContext(); @@ -245,13 +243,18 @@ protected void channelRead0(ChannelHandlerContext ctx, Object o) { Map properties = new HashMap<>(); properties.put(ObservabilityConstants.KEY_OBSERVER_CONTEXT, observerContext); - - StrandMetadata strandMetadata = new StrandMetadata(TEST_OBSERVE_PACKAGE.getOrg(), - TEST_OBSERVE_PACKAGE.getName(), TEST_OBSERVE_PACKAGE.getMajorVersion(), - resourceFunctionName); Utils.logInfo("Dispatching resource " + resourcePath); - runtime.invokeMethodAsync(serviceObject, resourceFunctionName, null, strandMetadata, - new WebServerCallableUnitCallback(ctx, resourcePath), properties, resource.getReturnType(), args); + ObjectType objectType = (ObjectType) serviceObject.getOriginalType(); + try { + boolean isConcurrentSafe = objectType.isIsolated() && objectType.isIsolated(resourceFunctionName); + StrandMetadata metadata = new StrandMetadata(isConcurrentSafe, properties); + Object result = env.getRuntime().callMethod(serviceObject, resourceFunctionName, metadata, args); + handleResult(ctx, result, resourcePath); + } catch (BError error) { + handleError(ctx, error, resourcePath); + } catch (Throwable cause) { + handleError(ctx, ErrorCreator.createError(cause), resourcePath); + } } @Override @@ -261,33 +264,17 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { ctx.close(); } - /** - * Callable unit used in executing ballerina resource function. - */ - public static class WebServerCallableUnitCallback implements Callback { - private final ChannelHandlerContext ctx; - private final String resourceName; - - public WebServerCallableUnitCallback(ChannelHandlerContext ctx, String resourcePath) { - this.ctx = ctx; - this.resourceName = resourcePath; - } - - @Override - public void notifySuccess(Object result) { - if (result instanceof BError) { - notifyFailure(((BError) result)); - } else { - Utils.logInfo("Successfully executed resource " + this.resourceName); - } + private void handleResult(ChannelHandlerContext ctx, Object result, String resourcePath) { + if (result instanceof BError error) { + handleError(ctx, error, resourcePath); + } else { + Utils.logInfo("Successfully executed resource " + resourcePath); } + } - @Override - public void notifyFailure(BError error) { - writeResponse(this.ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR, error.getMessage()); - Utils.logError("Failed to execute resource " + this.resourceName + " " - + error.getPrintableStackTrace()); - } + private void handleError(ChannelHandlerContext ctx, BError error, String resourcePath) { + writeResponse(ctx, HttpResponseStatus.INTERNAL_SERVER_ERROR, error.getMessage()); + Utils.logError("Failed to execute resource " + resourcePath + " " + error.getPrintableStackTrace()); } }