We are trying to migrate our existing Spark analysis engine to Java 17 with Springboot 3.2.5. As I understand this requires a latest version of Spark (v4.0-preview). However, we are getting the above error while creating a SparkSesison object as shown below:
this.sparkSession = SparkSession.builder()
.appName("Spark Session")
.master("local[*]")
.getOrCreate();
Following is the stack trace:
java.lang.NoClassDefFoundError: jakarta/servlet/SingleThreadModel
at org.sparkproject.jetty.servlet.ServletHolder.setServlet(ServletHolder.java:173) ~[spark-core_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at org.sparkproject.jetty.servlet.ServletHolder.<init>(ServletHolder.java:120) ~[spark-core_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at org.apache.spark.ui.JettyUtils$.createServletHandler(JettyUtils.scala:121) ~[spark-core_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at org.apache.spark.ui.SparkUI.<init>(SparkUI.scala:69) ~[spark-core_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at org.apache.spark.ui.SparkUI$.create(SparkUI.scala:248) ~[spark-core_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at org.apache.spark.SparkContext.<init>(SparkContext.scala:515) ~[spark-core_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at org.apache.spark.SparkContext$.getOrCreate(SparkContext.scala:2965) ~[spark-core_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at org.apache.spark.sql.SparkSession$Builder.$anonfun$getOrCreate$2(SparkSession.scala:1122) ~[spark-sql_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at scala.Option.getOrElse(Option.scala:201) ~[scala-library-2.13.14.jar:?]
at org.apache.spark.sql.SparkSession$Builder.getOrCreate(SparkSession.scala:1116) ~[spark-sql_2.13-4.0.0-preview1.jar:4.0.0-preview1]
at com.vislesha.jobengine.config.AnalysisExecutionJobConfig.lambda$setSparkSessionTask$0(AnalysisExecutionJobConfig.java:54) ~[classes/:?]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:388) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:312) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-6.1.6.jar:6.1.6]
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:255) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:369) ~[spring-batch-infrastructure-5.1.1.jar:5.1.1]
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:206) ~[spring-batch-infrastructure-5.1.1.jar:5.1.1]
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:140) ~[spring-batch-infrastructure-5.1.1.jar:5.1.1]
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:240) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:229) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:153) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.job.AbstractJob.handleStep(AbstractJob.java:418) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.job.SimpleJob.doExecute(SimpleJob.java:132) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:317) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:157) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-6.1.6.jar:6.1.6]
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:148) ~[spring-batch-core-5.1.1.jar:5.1.1]
at org.springframework.batch.core.launch.support.TaskExecutorJobLauncher.run(TaskExecutorJobLauncher.java:59) ~[spring-batch-core-5.1.1.jar:5.1.1]
at com.vislesha.JobEngineApplication$1.run(JobEngineApplication.java:43) ~[classes/:?]
at org.springframework.boot.SpringApplication.lambda$callRunner$4(SpringApplication.java:786) ~[spring-boot-3.2.5.jar:3.2.5]
at org.springframework.util.function.ThrowingConsumer$1.acceptWithException(ThrowingConsumer.java:83) ~[spring-core-6.1.6.jar:6.1.6]
at org.springframework.util.function.ThrowingConsumer.accept(ThrowingConsumer.java:60) ~[spring-core-6.1.6.jar:6.1.6]
at org.springframework.util.function.ThrowingConsumer$1.accept(ThrowingConsumer.java:88) ~[spring-core-6.1.6.jar:6.1.6]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:798) ~[spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:786) ~[spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.lambda$callRunners$3(SpringApplication.java:774) ~[spring-boot-3.2.5.jar:3.2.5]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) [?:?]
at java.base/java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:357) [?:?]
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:510) [?:?]
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) [?:?]
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) [?:?]
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) [?:?]
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) [?:?]
at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) [?:?]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:774) [spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:341) [spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) [spring-boot-3.2.5.jar:3.2.5]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) [spring-boot-3.2.5.jar:3.2.5]
at com.vislesha.JobEngineApplication.main(JobEngineApplication.java:32) [classes/:?]
Caused by: java.lang.ClassNotFoundException: jakarta.servlet.SingleThreadModel
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[?:?]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[?:?]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525) ~[?:?]
... 50 more
Request someone to provide a solution!
The SingleThreadModel
interface was dropped from Servlet 6.0 after two decades of deprecation.
Spring Boot 3 relies upon Jakarta Servlet 6.0, per Release Notes. Hence your error: That interface no longer exists.
➡️ You absolutely must write your servlet’s code to be thread-safe. Ditto for any libraries you call upon.
SingleThreadModel
dropped from Servlet 6+The javax.servlet.SingleThreadModel
interface was deprecated in Java Servlet API 2.4, with no direct replacement, on 24 Nov, 2003.
In Servlet 5, the package name changed to jakarta.servlet.SingleThreadModel
. The javax.
changed to jakarta.
.
This package renaming happened as part of the transition when Oracle donated Java EE technologies to the Eclipse Foundation to become Jakarta EE.
In Servlet 6.0 and later, the interface was dropped from the specification and API. To quote from the spec page outlining changes:
Remove API classes and methods that were deprecated in Servlet 5.0 and earlier. This includes removing the
SingleThreadModel
andHttpSessionContext
interfaces and theHttpUtils
class as well as various deprecated methods