diff --git a/README.md b/README.md
index 24d5ec04..63e1fd10 100644
--- a/README.md
+++ b/README.md
@@ -81,7 +81,7 @@ This repository only contains the source code for the package.
### Setting 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 b9ee8005..94f332a6 100644
--- a/ballerina/Ballerina.toml
+++ b/ballerina/Ballerina.toml
@@ -9,44 +9,44 @@ icon = "icon.png"
license = ["Apache-2.0"]
distribution = "2201.10.0"
-[platform.java17]
+[platform.java21]
graalvmCompatible = true
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.ballerina.stdlib"
artifactId = "udp-native"
version = "1.11.1"
path = "../native/build/libs/udp-native-1.11.1-SNAPSHOT.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
path = "../test-utils/build/libs/udp-test-utils-1.11.1-SNAPSHOT.jar"
scope = "testOnly"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-handler"
version = "4.1.115.Final"
path = "./lib/netty-handler-4.1.115.Final.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-buffer"
version = "4.1.115.Final"
path = "./lib/netty-buffer-4.1.115.Final.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-transport"
version = "4.1.115.Final"
path = "./lib/netty-transport-4.1.115.Final.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-common"
version = "4.1.115.Final"
path = "./lib/netty-common-4.1.115.Final.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-resolver"
version = "4.1.115.Final"
diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml
index 4d13fef4..de7bf99a 100644
--- a/ballerina/Dependencies.toml
+++ b/ballerina/Dependencies.toml
@@ -5,12 +5,12 @@
[ballerina]
dependencies-toml-version = "2"
-distribution-version = "2201.10.0"
+distribution-version = "2201.11.0-20241112-214900-6b80ab87"
[[package]]
org = "ballerina"
name = "io"
-version = "1.6.1"
+version = "1.6.2"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "jballerina.java"},
@@ -75,7 +75,7 @@ dependencies = [
[[package]]
org = "ballerina"
name = "log"
-version = "2.10.0"
+version = "2.10.1"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "io"},
@@ -90,7 +90,7 @@ modules = [
[[package]]
org = "ballerina"
name = "observe"
-version = "1.3.0"
+version = "1.4.0"
scope = "testOnly"
dependencies = [
{org = "ballerina", name = "jballerina.java"}
diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml
index b2bcadcb..13e7bb98 100644
--- a/build-config/resources/Ballerina.toml
+++ b/build-config/resources/Ballerina.toml
@@ -9,44 +9,44 @@ icon = "icon.png"
license = ["Apache-2.0"]
distribution = "2201.10.0"
-[platform.java17]
+[platform.java21]
graalvmCompatible = true
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.ballerina.stdlib"
artifactId = "udp-native"
version = "@toml.version@"
path = "../native/build/libs/udp-native-@project.version@.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
path = "../test-utils/build/libs/udp-test-utils-@project.version@.jar"
scope = "testOnly"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-handler"
version = "@netty.version@"
path = "./lib/netty-handler-@netty.version@.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-buffer"
version = "@netty.version@"
path = "./lib/netty-buffer-@netty.version@.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-transport"
version = "@netty.version@"
path = "./lib/netty-transport-@netty.version@.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-common"
version = "@netty.version@"
path = "./lib/netty-common-@netty.version@.jar"
-[[platform.java17.dependency]]
+[[platform.java21.dependency]]
groupId = "io.netty"
artifactId = "netty-resolver"
version = "@netty.version@"
diff --git a/build-config/spotbugs-exclude.xml b/build-config/spotbugs-exclude.xml
index 1603f89a..06f8da75 100644
--- a/build-config/spotbugs-exclude.xml
+++ b/build-config/spotbugs-exclude.xml
@@ -24,13 +24,12 @@
-
-
-
-
-
+
+
+
+
diff --git a/compiler-plugin-tests/build.gradle b/compiler-plugin-tests/build.gradle
index 4c687424..e52c92a1 100644
--- a/compiler-plugin-tests/build.gradle
+++ b/compiler-plugin-tests/build.gradle
@@ -52,8 +52,11 @@ checkstyle {
checkstyleTest.dependsOn(":checkstyle:downloadCheckstyleRuleFiles")
spotbugsTest {
- 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/compiler-plugin/build.gradle b/compiler-plugin/build.gradle
index d85207b5..bcd2a22d 100644
--- a/compiler-plugin/build.gradle
+++ b/compiler-plugin/build.gradle
@@ -48,8 +48,11 @@ 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/gradle.properties b/gradle.properties
index de57f474..eea1a1ef 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,12 +1,12 @@
org.gradle.caching=true
group=io.ballerina.stdlib
version=1.11.1-SNAPSHOT
-ballerinaLangVersion=2201.10.0
+ballerinaLangVersion=2201.11.0-20241112-214900-6b80ab87
puppycrawlCheckstyleVersion=10.12.0
githubJohnrengelmanShadowVersion=8.1.1
checkstyleToolVersion=7.8.2
-githubSpotbugsVersion=5.0.14
+githubSpotbugsVersion=6.0.18
testngVersion=7.6.1
nettyVersion=4.1.115.Final
underCouchDownloadVersion=5.4.0
@@ -16,7 +16,7 @@ ballerinaGradlePluginVersion=2.0.1
gsonVersion=2.8.8
# Dependencies
-stdlibIoVersion=1.6.0
-stdlibLogVersion=2.10.0
-observeVersion=1.3.0
-observeInternalVersion=1.3.0
+stdlibIoVersion=1.6.2-20241112-233100-995cf5f
+stdlibLogVersion=2.10.1-20241113-120000-4577868
+observeVersion=1.4.0-20241113-092000-b83ae74
+observeInternalVersion=1.3.1-20241113-101700-265054d
diff --git a/native/build.gradle b/native/build.gradle
index c2235fee..c7cb303e 100644
--- a/native/build.gradle
+++ b/native/build.gradle
@@ -61,8 +61,11 @@ compileJava {
}
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/native/src/main/java/io/ballerina/stdlib/udp/Dispatcher.java b/native/src/main/java/io/ballerina/stdlib/udp/Dispatcher.java
index d1efe5ae..6a96dab2 100644
--- a/native/src/main/java/io/ballerina/stdlib/udp/Dispatcher.java
+++ b/native/src/main/java/io/ballerina/stdlib/udp/Dispatcher.java
@@ -19,21 +19,28 @@
package io.ballerina.stdlib.udp;
import io.ballerina.runtime.api.Runtime;
-import io.ballerina.runtime.api.TypeTags;
-import io.ballerina.runtime.api.async.StrandMetadata;
+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.MethodType;
import io.ballerina.runtime.api.types.ObjectType;
+import io.ballerina.runtime.api.types.Parameter;
import io.ballerina.runtime.api.types.Type;
+import io.ballerina.runtime.api.types.TypeTags;
import io.ballerina.runtime.api.utils.StringUtils;
import io.ballerina.runtime.api.utils.TypeUtils;
+import io.ballerina.runtime.api.values.BArray;
import io.ballerina.runtime.api.values.BError;
+import io.ballerina.runtime.api.values.BMap;
import io.ballerina.runtime.api.values.BObject;
+import io.ballerina.runtime.api.values.BString;
+import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.socket.DatagramPacket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.InetSocketAddress;
import java.util.Arrays;
/**
@@ -49,8 +56,7 @@ private static void invokeOnBytes(UdpService udpService, DatagramPacket datagram
Type[] parameterTypes) {
try {
Object[] params = getOnBytesSignature(datagramPacket, channel, parameterTypes);
- invokeAsyncCall(udpService.getService(), Constants.ON_BYTES, udpService.getRuntime(),
- new UdpCallback(udpService, channel, datagramPacket), params);
+ invokeAsyncCall(udpService, datagramPacket, channel, Constants.ON_BYTES, params);
} catch (BError e) {
Dispatcher.invokeOnError(udpService, e.getMessage());
}
@@ -60,8 +66,7 @@ private static void invokeOnDatagram(UdpService udpService, DatagramPacket datag
Type[] parameterTypes) {
try {
Object[] params = getOnDatagramSignature(datagramPacket, channel, parameterTypes);
- invokeAsyncCall(udpService.getService(), Constants.ON_DATAGRAM, udpService.getRuntime(),
- new UdpCallback(udpService, channel, datagramPacket), params);
+ invokeAsyncCall(udpService, datagramPacket, channel, Constants.ON_DATAGRAM, params);
} catch (BError e) {
Dispatcher.invokeOnError(udpService, e.getMessage());
}
@@ -75,44 +80,47 @@ public static void invokeOnError(UdpService udpService, String message) {
filter(m -> m.getName().equals(Constants.ON_ERROR)).findFirst().orElse(null);
if (methodType != null) {
Object[] params = getOnErrorSignature(message);
- invokeAsyncCall(udpService.getService(), Constants.ON_ERROR, udpService.getRuntime(),
- new UdpCallback(udpService), params);
+ invokeAsyncCall(udpService, null, null, Constants.ON_ERROR, params);
}
} catch (Throwable t) {
log.error("Error while executing onError function", t);
}
}
- private static void invokeAsyncCall(BObject service, String methodName, Runtime runtime, UdpCallback callback,
- Object[] params) {
- StrandMetadata metadata = new StrandMetadata(Utils.getModule().getOrg(), Utils.getModule().getName(),
- Utils.getModule().getVersion(), methodName);
- ObjectType objectType = (ObjectType) TypeUtils.getReferredType(TypeUtils.getType(service));
- if (objectType.isIsolated() && objectType.isIsolated(methodName)) {
- runtime.invokeMethodAsyncConcurrently(service, methodName,
- null, metadata, callback, null, null, params);
- } else {
- runtime.invokeMethodAsyncSequentially(service, methodName,
- null, metadata, callback, null, null, params);
- }
+ private static void invokeAsyncCall(UdpService udpService, DatagramPacket datagramPacket, Channel channel,
+ String methodName, Object[] params) {
+ Thread.startVirtualThread(() -> {
+ BObject service = udpService.getService();
+ Runtime runtime = udpService.getRuntime();
+ ObjectType objectType = (ObjectType) TypeUtils.getReferredType(TypeUtils.getType(service));
+ StrandMetadata metadata = new StrandMetadata(
+ objectType.isIsolated() && objectType.isIsolated(methodName), null);
+ Object result;
+ try {
+ result = runtime.callMethod(service, methodName, metadata, params);
+ handleResult(udpService, datagramPacket, channel, result);
+ } catch (BError error) {
+ handleError(error);
+ } catch (Throwable throwable) {
+ handleError(ErrorCreator.createError(throwable));
+ }
+ });
}
private static Object[] getOnBytesSignature(DatagramPacket datagramPacket, Channel channel, Type[] parameterTypes) {
byte[] byteContent = new byte[datagramPacket.content().readableBytes()];
datagramPacket.content().readBytes(byteContent);
- Object[] bValues = new Object[parameterTypes.length * 2];
+ Object[] bValues = new Object[parameterTypes.length];
int index = 0;
for (Type param : parameterTypes) {
int paramTag = param.getTag();
switch (paramTag) {
case TypeTags.INTERSECTION_TAG:
bValues[index++] = ValueCreator.createReadonlyArrayValue(byteContent);
- bValues[index++] = true;
break;
case TypeTags.OBJECT_TYPE_TAG:
bValues[index++] = createClient(datagramPacket, channel);
- bValues[index++] = true;
break;
default:
break;
@@ -123,18 +131,16 @@ private static Object[] getOnBytesSignature(DatagramPacket datagramPacket, Chann
private static Object[] getOnDatagramSignature(DatagramPacket datagramPacket, Channel channel,
Type[] parameterTypes) {
- Object[] bValues = new Object[parameterTypes.length * 2];
+ Object[] bValues = new Object[parameterTypes.length];
int index = 0;
for (Type param : parameterTypes) {
int paramTag = param.getTag();
switch (paramTag) {
case TypeTags.INTERSECTION_TAG:
bValues[index++] = Utils.createReadOnlyDatagramWithSenderAddress(datagramPacket);
- bValues[index++] = true;
break;
case TypeTags.OBJECT_TYPE_TAG:
bValues[index++] = createClient(datagramPacket, channel);
- bValues[index++] = true;
break;
default:
break;
@@ -144,7 +150,7 @@ private static Object[] getOnDatagramSignature(DatagramPacket datagramPacket, Ch
}
private static Object[] getOnErrorSignature(String message) {
- return new Object[]{Utils.createUdpError(message), true};
+ return new Object[]{Utils.createUdpError(message)};
}
private static BObject createClient(DatagramPacket datagramPacket, Channel channel) {
@@ -159,19 +165,55 @@ private static BObject createClient(DatagramPacket datagramPacket, Channel chann
public static void invokeRead(UdpService udpService, DatagramPacket datagramPacket, Channel channel) {
ObjectType objectType =
(ObjectType) TypeUtils.getReferredType(TypeUtils.getType(udpService.getService()));
+
for (MethodType method : objectType.getMethods()) {
switch (method.getName()) {
case Constants.ON_BYTES:
Dispatcher.invokeOnBytes(udpService, datagramPacket, channel,
- method.getType().getParameterTypes());
+ getParameterTypes(method.getType().getParameters()));
break;
case Constants.ON_DATAGRAM:
Dispatcher.invokeOnDatagram(udpService, datagramPacket, channel,
- method.getType().getParameterTypes());
+ getParameterTypes(method.getType().getParameters()));
break;
default:
break;
}
}
}
+
+ private static Type[] getParameterTypes(Parameter[] parameters) {
+ Type[] parameterTypes = new Type[parameters.length];
+ for (int i = 0; i < parameters.length; i++) {
+ parameterTypes[i] = parameters[i].type;
+ }
+ return parameterTypes;
+ }
+
+ private static void handleResult(UdpService udpService, DatagramPacket datagramP, Channel channel, Object object) {
+ if (object instanceof BArray) {
+ // call writeBytes if the service returns byte[]
+ byte[] byteContent = ((BArray) object).getBytes();
+ UdpListener.send(udpService, new DatagramPacket(Unpooled.wrappedBuffer(byteContent),
+ datagramP.sender()), channel);
+ } else if (object instanceof BMap) {
+ // call sendDatagram if the service returns Datagram
+ BMap datagram = (BMap) object;
+ String host = datagram.getStringValue(StringUtils.fromString(Constants.DATAGRAM_REMOTE_HOST)).getValue();
+ int port = datagram.getIntValue(StringUtils.fromString(Constants.DATAGRAM_REMOTE_PORT)).intValue();
+ BArray data = datagram.getArrayValue(StringUtils.fromString(Constants.DATAGRAM_DATA));
+ byte[] byteContent = data.getBytes();
+ DatagramPacket datagramPacket = new DatagramPacket(Unpooled.wrappedBuffer(byteContent),
+ new InetSocketAddress(host, port));
+ UdpListener.send(udpService, datagramPacket, channel);
+ } else if (object instanceof BError) {
+ ((BError) object).printStackTrace();
+ }
+ log.debug("Method successfully dispatched.");
+ }
+
+
+ public static void handleError(BError bError) {
+ bError.printStackTrace();
+ }
}
diff --git a/native/src/main/java/io/ballerina/stdlib/udp/UdpCallback.java b/native/src/main/java/io/ballerina/stdlib/udp/UdpCallback.java
deleted file mode 100644
index dc4c0601..00000000
--- a/native/src/main/java/io/ballerina/stdlib/udp/UdpCallback.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2021 WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
- *
- * WSO2 Inc. licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package io.ballerina.stdlib.udp;
-
-import io.ballerina.runtime.api.async.Callback;
-import io.ballerina.runtime.api.utils.StringUtils;
-import io.ballerina.runtime.api.values.BArray;
-import io.ballerina.runtime.api.values.BError;
-import io.ballerina.runtime.api.values.BMap;
-import io.ballerina.runtime.api.values.BString;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.Channel;
-import io.netty.channel.socket.DatagramPacket;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.InetSocketAddress;
-
-/**
- * callback implementation.
- */
-public class UdpCallback implements Callback {
-
- private static final Logger log = LoggerFactory.getLogger(UdpCallback.class);
-
- private UdpService udpService;
- private Channel channel;
- private DatagramPacket datagram;
-
- public UdpCallback(UdpService udpService, Channel channel, DatagramPacket datagram) {
- this.udpService = udpService;
- this.channel = channel;
- this.datagram = datagram;
- }
-
- public UdpCallback(UdpService udpService) {
- this.udpService = udpService;
- }
-
- public UdpCallback() {}
-
- @Override
- public void notifySuccess(Object object) {
- if (object instanceof BArray) {
- // call writeBytes if the service returns byte[]
- byte[] byteContent = ((BArray) object).getBytes();
- UdpListener.send(udpService, new DatagramPacket(Unpooled.wrappedBuffer(byteContent),
- datagram.sender()), channel);
- } else if (object instanceof BMap) {
- // call sendDatagram if the service returns Datagram
- BMap datagram = (BMap) object;
- String host = datagram.getStringValue(StringUtils.fromString(Constants.DATAGRAM_REMOTE_HOST)).getValue();
- int port = datagram.getIntValue(StringUtils.fromString(Constants.DATAGRAM_REMOTE_PORT)).intValue();
- BArray data = datagram.getArrayValue(StringUtils.fromString(Constants.DATAGRAM_DATA));
- byte[] byteContent = data.getBytes();
- DatagramPacket datagramPacket = new DatagramPacket(Unpooled.wrappedBuffer(byteContent),
- new InetSocketAddress(host, port));
- UdpListener.send(udpService, datagramPacket, channel);
- } else if (object instanceof BError) {
- ((BError) object).printStackTrace();
- }
- log.debug("Method successfully dispatched.");
- }
-
- @Override
- public void notifyFailure(BError bError) {
- bError.printStackTrace();
- }
-}
diff --git a/native/src/main/java/io/ballerina/stdlib/udp/UdpClient.java b/native/src/main/java/io/ballerina/stdlib/udp/UdpClient.java
index fff47def..774039cd 100644
--- a/native/src/main/java/io/ballerina/stdlib/udp/UdpClient.java
+++ b/native/src/main/java/io/ballerina/stdlib/udp/UdpClient.java
@@ -18,7 +18,6 @@
package io.ballerina.stdlib.udp;
-import io.ballerina.runtime.api.Future;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
@@ -33,6 +32,7 @@
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.LinkedList;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
@@ -45,7 +45,7 @@ public class UdpClient {
// create connection oriented client
public UdpClient(InetSocketAddress localAddress, InetSocketAddress remoteAddress,
- EventLoopGroup group, Future callback) {
+ EventLoopGroup group, CompletableFuture