diff --git a/README.md b/README.md index 85b0b989..20e520e7 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ This repository only contains the source code for the package. ## Build from the source ### 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/) * [OpenJDK](https://adoptium.net/) diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 6d70d8f4..f2325cd1 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -9,14 +9,14 @@ icon = "icon.png" license = ["Apache-2.0"] distribution = "2201.8.0" -[platform.java17] +[platform.java21] graalvmCompatible = true -[[platform.java17.dependency]] +[[platform.java21.dependency]] groupId = "io.ballerina.stdlib" artifactId = "task-native" version = "2.5.1" path = "../native/build/libs/task-native-2.5.1-SNAPSHOT.jar" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "./lib/quartz-2.3.2.jar" diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index 8bb61713..af376d58 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -9,14 +9,14 @@ icon = "icon.png" license = ["Apache-2.0"] distribution = "2201.8.0" -[platform.java17] +[platform.java21] graalvmCompatible = true -[[platform.java17.dependency]] +[[platform.java21.dependency]] groupId = "io.ballerina.stdlib" artifactId = "task-native" version = "@toml.version@" path = "../native/build/libs/task-native-@project.version@.jar" -[[platform.java17.dependency]] +[[platform.java21.dependency]] path = "./lib/quartz-@quartz.version@.jar" diff --git a/gradle.properties b/gradle.properties index f5c7ec5b..22b485a1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,11 +2,11 @@ org.gradle.caching=true group=io.ballerina.stdlib version=2.5.1-SNAPSHOT -ballerinaLangVersion=2201.8.0 +ballerinaLangVersion=2201.11.0-20241117-133400-a3054b77 axiomVersion=1.2.22 puppycrawlCheckstyleVersion=10.12.0 ballerinaGradlePluginVersion=2.0.1 -githubSpotbugsVersion=5.0.14 +githubSpotbugsVersion=6.0.18 githubJohnrengelmanShadowVersion=7.1.2 underCouchDownloadVersion=5.4.0 researchgateReleaseVersion=2.8.0 @@ -14,4 +14,4 @@ researchgateReleaseVersion=2.8.0 quartzVersion=2.3.2 #stdlib dependencies -stdlibTimeVersion=2.4.0 +stdlibTimeVersion=2.6.0-20241113-073800-201b904 diff --git a/native/build.gradle b/native/build.gradle index 0b0ce11d..3cac75b3 100644 --- a/native/build.gradle +++ b/native/build.gradle @@ -46,8 +46,12 @@ tasks.withType(Checkstyle) { } spotbugsMain { - effort "max" - reportLevel "low" + ignoreFailures = true + 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/task/utils/TaskCallBack.java b/native/src/main/java/io/ballerina/stdlib/task/utils/TaskCallBack.java deleted file mode 100644 index 0946edc4..00000000 --- a/native/src/main/java/io/ballerina/stdlib/task/utils/TaskCallBack.java +++ /dev/null @@ -1,74 +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.task.utils; - -import io.ballerina.runtime.api.async.Callback; -import io.ballerina.runtime.api.values.BError; -import org.quartz.JobExecutionContext; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; - -import java.io.PrintStream; - -/** - * The class handles the output of job execution by the trigger. - * - * @since 2.0.0 - */ -public class TaskCallBack implements Callback { - - JobExecutionContext jobExecutionContext; - private static PrintStream console = System.out; - - public TaskCallBack(JobExecutionContext jobExecutionContext) { - this.jobExecutionContext = jobExecutionContext; - } - - @Override - public void notifySuccess(Object o) { - } - - @Override - public void notifyFailure(BError bError) { - Scheduler scheduler = jobExecutionContext.getScheduler(); - String errorPolicy = (String) jobExecutionContext.getMergedJobDataMap().get(TaskConstants.ERROR_POLICY); - String jobId = (String) jobExecutionContext.getMergedJobDataMap().get(TaskConstants.JOB_ID); - if (isLogged(errorPolicy)) { - Utils.printMessage("Unable to execute the job[" + jobId + "]. " + bError.getMessage(), console); - } - if (isTerminated(errorPolicy)) { - try { - scheduler.unscheduleJob(this.jobExecutionContext.getTrigger().getKey()); - } catch (SchedulerException e) { - if (errorPolicy.equalsIgnoreCase(TaskConstants.LOG_AND_TERMINATE)) { - Utils.printMessage(e.toString(), console); - } - } - } - } - - private boolean isLogged(String errorPolicy) { - return errorPolicy.equalsIgnoreCase(TaskConstants.LOG_AND_TERMINATE) || - errorPolicy.equalsIgnoreCase(TaskConstants.LOG_AND_CONTINUE); - } - - private boolean isTerminated(String errorPolicy) { - return errorPolicy.equalsIgnoreCase(TaskConstants.LOG_AND_TERMINATE) || - errorPolicy.equalsIgnoreCase(TaskConstants.TERMINATE); - } -} diff --git a/native/src/main/java/io/ballerina/stdlib/task/utils/TaskJob.java b/native/src/main/java/io/ballerina/stdlib/task/utils/TaskJob.java index 023add4c..9c12fc32 100644 --- a/native/src/main/java/io/ballerina/stdlib/task/utils/TaskJob.java +++ b/native/src/main/java/io/ballerina/stdlib/task/utils/TaskJob.java @@ -18,7 +18,10 @@ package io.ballerina.stdlib.task.utils; import io.ballerina.runtime.api.Runtime; -import io.ballerina.runtime.api.async.Callback; +import io.ballerina.runtime.api.concurrent.StrandMetadata; +import io.ballerina.runtime.api.creators.ErrorCreator; +import io.ballerina.runtime.api.types.ObjectType; +import io.ballerina.runtime.api.values.BError; import io.ballerina.runtime.api.values.BObject; import io.ballerina.stdlib.task.objects.TaskManager; import org.quartz.Job; @@ -37,9 +40,19 @@ public TaskJob() { */ @Override public void execute(JobExecutionContext jobExecutionContext) { - Runtime runtime = TaskManager.getInstance().getRuntime(); - BObject job = (BObject) jobExecutionContext.getMergedJobDataMap().get(TaskConstants.JOB); - Callback callback = new TaskCallBack(jobExecutionContext); - runtime.invokeMethodAsync(job, TaskConstants.EXECUTE, null, null, callback); + Thread.startVirtualThread(() -> { + Runtime runtime = TaskManager.getInstance().getRuntime(); + BObject job = (BObject) jobExecutionContext.getMergedJobDataMap().get(TaskConstants.JOB); + try { + ObjectType objectType = (ObjectType) job.getOriginalType(); + boolean isConcurrentSafe = objectType.isIsolated() && objectType.isIsolated(TaskConstants.EXECUTE); + StrandMetadata metadata = new StrandMetadata(isConcurrentSafe, null); + runtime.callMethod(job, TaskConstants.EXECUTE, metadata); + } catch (BError error) { + Utils.notifyFailure(jobExecutionContext, error); + } catch (Throwable t) { + Utils.notifyFailure(jobExecutionContext, ErrorCreator.createError(t)); + } + }); } } diff --git a/native/src/main/java/io/ballerina/stdlib/task/utils/Utils.java b/native/src/main/java/io/ballerina/stdlib/task/utils/Utils.java index 75559961..df4534ec 100644 --- a/native/src/main/java/io/ballerina/stdlib/task/utils/Utils.java +++ b/native/src/main/java/io/ballerina/stdlib/task/utils/Utils.java @@ -17,8 +17,8 @@ */ package io.ballerina.stdlib.task.utils; -import io.ballerina.runtime.api.TypeTags; import io.ballerina.runtime.api.creators.ErrorCreator; +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.BError; @@ -26,6 +26,7 @@ import org.quartz.JobBuilder; import org.quartz.JobDataMap; import org.quartz.JobDetail; +import org.quartz.JobExecutionContext; import org.quartz.Scheduler; import org.quartz.SchedulerException; import org.quartz.SimpleScheduleBuilder; @@ -58,6 +59,8 @@ private Utils() {} private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + private static final PrintStream console = System.out; + public static BError createTaskError(String message) { return ErrorCreator.createDistinctError(TaskConstants.ERROR, ModuleUtils.getModule(), StringUtils.fromString(message)); @@ -164,4 +167,32 @@ public static void disableQuartzLogs() { public static boolean isInt(Object time) { return TypeUtils.getType(time).getTag() == TypeTags.INT_TAG; } + + public static void notifyFailure(JobExecutionContext jobExecutionContext, BError bError) { + Scheduler scheduler = jobExecutionContext.getScheduler(); + String errorPolicy = (String) jobExecutionContext.getMergedJobDataMap().get(TaskConstants.ERROR_POLICY); + String jobId = (String) jobExecutionContext.getMergedJobDataMap().get(TaskConstants.JOB_ID); + if (isLogged(errorPolicy)) { + Utils.printMessage("Unable to execute the job[" + jobId + "]. " + bError.getMessage(), console); + } + if (isTerminated(errorPolicy)) { + try { + scheduler.unscheduleJob(jobExecutionContext.getTrigger().getKey()); + } catch (SchedulerException e) { + if (errorPolicy.equalsIgnoreCase(TaskConstants.LOG_AND_TERMINATE)) { + Utils.printMessage(e.toString(), console); + } + } + } + } + + private static boolean isLogged(String errorPolicy) { + return errorPolicy.equalsIgnoreCase(TaskConstants.LOG_AND_TERMINATE) || + errorPolicy.equalsIgnoreCase(TaskConstants.LOG_AND_CONTINUE); + } + + private static boolean isTerminated(String errorPolicy) { + return errorPolicy.equalsIgnoreCase(TaskConstants.LOG_AND_TERMINATE) || + errorPolicy.equalsIgnoreCase(TaskConstants.TERMINATE); + } } diff --git a/native/src/main/java/module-info.java b/native/src/main/java/module-info.java index ef8f5a87..5c33de65 100644 --- a/native/src/main/java/module-info.java +++ b/native/src/main/java/module-info.java @@ -20,6 +20,7 @@ requires io.ballerina.runtime; requires quartz; requires java.logging; + requires io.ballerina.lang; exports io.ballerina.stdlib.task.actions; exports io.ballerina.stdlib.task.exceptions; exports io.ballerina.stdlib.task.objects;