diff --git a/rules/pom.xml b/rules/pom.xml
index 281fada02..1dc6a72eb 100644
--- a/rules/pom.xml
+++ b/rules/pom.xml
@@ -378,6 +378,7 @@
eap6/api-jars/*.jar
eap7/api-jars/*.jar
openjdk11/api-jars/*.jar
+ quarkus/api-jars/*.jar
**/*.xsl
**/rewrite.yml
diff --git a/rules/rules-reviewed/quarkus/api-jars/jakarta.ejb-api-4.0.0.jar b/rules/rules-reviewed/quarkus/api-jars/jakarta.ejb-api-4.0.0.jar
new file mode 100644
index 000000000..0ba845463
Binary files /dev/null and b/rules/rules-reviewed/quarkus/api-jars/jakarta.ejb-api-4.0.0.jar differ
diff --git a/rules/rules-reviewed/quarkus/api-jars/jakarta.enterprise.cdi-api-4.0.0.jar b/rules/rules-reviewed/quarkus/api-jars/jakarta.enterprise.cdi-api-4.0.0.jar
new file mode 100644
index 000000000..461eb235e
Binary files /dev/null and b/rules/rules-reviewed/quarkus/api-jars/jakarta.enterprise.cdi-api-4.0.0.jar differ
diff --git a/rules/rules-reviewed/quarkus/java-ee/cdi-to-quarkus.windup.groovy b/rules/rules-reviewed/quarkus/java-ee/cdi-to-quarkus.windup.groovy
index 998f974b9..a87ff32a2 100644
--- a/rules/rules-reviewed/quarkus/java-ee/cdi-to-quarkus.windup.groovy
+++ b/rules/rules-reviewed/quarkus/java-ee/cdi-to-quarkus.windup.groovy
@@ -72,6 +72,7 @@ ruleSet("cdi-to-quarkus-groovy")
void perform(GraphRewrite event, EvaluationContext context, JavaAnnotationTypeReferenceModel payload) {
final String annotatedClass = payload.getAnnotatedType().getResolvedSourceSnippit()
+ System.out.println("ANNOTATED TYPE: " + annotatedClass)
final boolean injectedClassHasScopeAnnotations =
JavaClass.references(annotatedClass)
.at(TypeReferenceLocation.TYPE)
@@ -87,8 +88,8 @@ ruleSet("cdi-to-quarkus-groovy")
if (!injectedClassHasScopeAnnotations && !injectedClassHasSingletonAnnotations) {
// first of all select only the file belonging to the same root project as the payload
// to reduce (i.e. optimize) the number of files found from the second query
- if (Query.fromType(FileModel.class).withProperty(FileModel.FILE_PATH, QueryPropertyComparisonType.CONTAINS_TOKEN, payload.getFile().getProjectModel().getRootFileModel().getPrettyPath() + "/").as(FROM_FILES_IN_PROJECT).evaluate(event, context)
- && JavaClass.from(FROM_FILES_IN_PROJECT).references(annotatedClass).at(TypeReferenceLocation.TYPE).as(INJECT_CLASS_DECLARATION).evaluate(event, context)) {
+ Query.fromType(FileModel.class).withProperty(FileModel.FILE_PATH, QueryPropertyComparisonType.CONTAINS_TOKEN, payload.getFile().getProjectModel().getRootFileModel().getPrettyPath() + "/").as(FROM_FILES_IN_PROJECT).evaluate(event, context)
+ JavaClass.from(FROM_FILES_IN_PROJECT).references(annotatedClass).at(TypeReferenceLocation.TYPE).as(INJECT_CLASS_DECLARATION).evaluate(event, context)
Iteration.over(INJECT_CLASS_DECLARATION)
.perform(
((Hint) Hint.titled("Injected class is missing scope annotation")
@@ -99,18 +100,17 @@ ruleSet("cdi-to-quarkus-groovy")
.withIssueCategory(potentialIssueCategory)
.with(guideLink)
.with(cdiSpecLink)
- .withEffort(1)
- )
+ .withEffort(1))
)
.endIteration()
- }
+
}
}
}
)
.endIteration()
)
- .withId("cdi-to-quarkus-groovy-00010")
+ .withId("cdi-to-quarkus-groovy-00010")
// suggest to replace cdi-api TRANSITIVE dependency if no Quarkus dependency has been already added and 'javax.enterprise.{packages}.{*}' package is used somewhere in the code
.addRule()
.when(
diff --git a/rules/rules-reviewed/quarkus/java-ee/jakarta-cdi-to-quarkus.windup.groovy b/rules/rules-reviewed/quarkus/java-ee/jakarta-cdi-to-quarkus.windup.groovy
new file mode 100644
index 000000000..18979597a
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/jakarta-cdi-to-quarkus.windup.groovy
@@ -0,0 +1,178 @@
+package quarkus.javaee
+
+import org.jboss.windup.ast.java.data.TypeReferenceLocation
+import org.jboss.windup.config.GraphRewrite
+import org.jboss.windup.config.Variables
+import org.jboss.windup.config.metadata.TechnologyReference
+import org.jboss.windup.config.operation.Iteration
+import org.jboss.windup.config.operation.iteration.AbstractIterationOperation
+import org.jboss.windup.config.query.Query
+import org.jboss.windup.config.query.QueryPropertyComparisonType
+import org.jboss.windup.graph.model.FileLocationModel
+import org.jboss.windup.graph.model.FileReferenceModel
+import org.jboss.windup.graph.model.ProjectModel
+import org.jboss.windup.graph.model.WindupVertexFrame
+import org.jboss.windup.graph.model.resource.FileModel
+import org.jboss.windup.reporting.category.IssueCategory
+import org.jboss.windup.reporting.category.IssueCategoryRegistry
+import org.jboss.windup.reporting.config.Hint
+import org.jboss.windup.reporting.config.Link
+import org.jboss.windup.rules.apps.java.condition.JavaClass
+import org.jboss.windup.rules.apps.java.condition.annotation.AnnotationTypeCondition
+import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationTypeReferenceModel
+import org.jboss.windup.rules.apps.xml.condition.XmlFile
+import org.ocpsoft.rewrite.config.And
+import org.ocpsoft.rewrite.config.Or
+import org.ocpsoft.rewrite.context.EvaluationContext
+
+import java.util.stream.Collectors
+import java.util.stream.StreamSupport
+
+final IssueCategory potentialIssueCategory = new IssueCategoryRegistry().getByID(IssueCategoryRegistry.POTENTIAL)
+final Link guideLink = Link.to("Quarkus - Guides", "https://quarkus.io/guides/cdi-reference")
+final Link cdiSpecLink = Link.to("CDI 2.0 - Scopes: Default scope", "https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#default_scope")
+
+static boolean matchesProject(GraphRewrite event, FileLocationModel payload) {
+ final Iterable extends WindupVertexFrame> previouslyFound = Optional.ofNullable(Variables.instance(event).findVariable("discard")).orElse(Collections.emptySet())
+ final Set projectModels = StreamSupport.stream(previouslyFound.spliterator(), false)
+ .map {
+ if (it instanceof FileReferenceModel) return ((FileReferenceModel) it).getFile().getProjectModel()
+ else if (it instanceof FileModel) return ((FileModel) it).getProjectModel()
+ else return null
+ }
+ .collect (Collectors.toSet())
+ final boolean matchesProject = projectModels.isEmpty() || projectModels.stream().anyMatch{payload.getFile().belongsToProject(it)}
+ return matchesProject
+}
+
+ruleSet("jakarta-cdi-to-quarkus-groovy")
+ .addSourceTechnology(new TechnologyReference("java-ee", null))
+ .addTargetTechnology(new TechnologyReference("quarkus", null))
+// this rule si required for Windup to know about storing data related to the classes involved in the
+// `when` condition because useful later on in the `perform` step of the next rule
+ .addRule()
+ .when(
+ Or.any(
+ JavaClass.references("jakarta.enterprise.context.{scope}").at(TypeReferenceLocation.ANNOTATION).as("placeholder1"),
+ JavaClass.references("jakarta.inject.Singleton").at(TypeReferenceLocation.ANNOTATION).as("placeholder2"),
+ )
+ )
+ .where("scope").matches("(ApplicationScoped|ConversationScoped|Dependent|RequestScoped|SessionScoped)")
+ .withId("jakarta-cdi-to-quarkus-groovy-00000")
+ .addRule()
+ .when(
+ JavaClass.references("jakarta.inject.Inject").at(TypeReferenceLocation.ANNOTATION).as("main")
+ )
+ .perform(
+ Iteration.over("main")
+ .perform(
+ new AbstractIterationOperation() {
+ public static final String FROM_FILES_IN_PROJECT = "filesInProject"
+ public static final String INJECT_CLASS_DECLARATION = "injectClassDeclaration"
+
+ void perform(GraphRewrite event, EvaluationContext context, JavaAnnotationTypeReferenceModel payload) {
+ final String annotatedClass = payload.getAnnotatedType().getResolvedSourceSnippit()
+ final boolean injectedClassHasScopeAnnotations =
+ JavaClass.references(annotatedClass)
+ .at(TypeReferenceLocation.TYPE)
+ .annotationMatches(new AnnotationTypeCondition("jakarta.enterprise.context.(ApplicationScoped|ConversationScoped|Dependent|RequestScoped|SessionScoped)"))
+ .as("discard")
+ .evaluate(event, context)
+ final boolean injectedClassHasSingletonAnnotations =
+ JavaClass.references(annotatedClass)
+ .at(TypeReferenceLocation.TYPE)
+ .annotationMatches(new AnnotationTypeCondition("jakarta.inject.Singleton"))
+ .as("discardAsWell")
+ .evaluate(event, context)
+ if (!injectedClassHasScopeAnnotations && !injectedClassHasSingletonAnnotations) {
+ // first of all select only the file belonging to the same root project as the payload
+ // to reduce (i.e. optimize) the number of files found from the second query
+ final FileModel fileModel = payload.getFile()
+ final String filePath = fileModel.getProjectModel().getRootFileModel().getPrettyPath() + "/"
+ Query.fromType(FileModel.class).withProperty(FileModel.FILE_PATH, QueryPropertyComparisonType.CONTAINS_TOKEN, filePath).as(FROM_FILES_IN_PROJECT).evaluate(event, context)
+ //Query.fromType(FileModel.class).withProperty(JavaClass.from
+ JavaClass.from(FROM_FILES_IN_PROJECT).references(annotatedClass).at(TypeReferenceLocation.TYPE).as(INJECT_CLASS_DECLARATION).evaluate(event, context)
+ Iteration.over(INJECT_CLASS_DECLARATION)
+ .perform(
+ ((Hint) Hint.titled("Injected class is missing scope annotation")
+ .withText("""
+ A class injected but missing an annotation to define its scope type is not going to be discovered from Quarkus.
+ Consider adding the `@Dependent` scope which is the default scope for a bean which does not explicitly declare a scope type (ref. [CDI 2.0 - Scopes: Default scope](https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#default_scope))
+ """)
+ .withIssueCategory(potentialIssueCategory)
+ .with(guideLink)
+ .with(cdiSpecLink)
+ .withEffort(1))
+ )
+ .endIteration()
+ }
+ }
+ }
+ )
+ .endIteration()
+ )
+ .withId("jakarta-cdi-to-quarkus-groovy-00010")
+// suggest to replace cdi-api TRANSITIVE dependency if no Quarkus dependency has been already added and 'javax.enterprise.{packages}.{*}' package is used somewhere in the code
+ .addRule()
+ .when(
+ And.all(
+ JavaClass.references("jakarta.enterprise.{packages}.{*}").at(TypeReferenceLocation.ANNOTATION).as("discard"),
+ XmlFile.matchesXpath("/m:project/m:dependencies[count(m:dependency/m:artifactId[contains(., 'cdi-api')]) = 0 and count(m:dependency/m:artifactId[contains(., 'quarkus-')]) = 0]")
+ .inFile("pom.xml")
+ .namespace("m", "http://maven.apache.org/POM/4.0.0")
+ .as("dependencies-section")
+ )
+ )
+ .perform(
+ Iteration.over("dependencies-section").perform(
+ new AbstractIterationOperation() {
+ void perform(GraphRewrite event, EvaluationContext context, FileLocationModel payload) {
+ if (matchesProject(event, payload)) {
+ ((Hint) Hint.titled("Remove jakarta.enterprise:cdi-api transitive dependency")
+ .withText("""
+ Transitive dependency `jakarta.enterprise:cdi-api` should be removed and the `io.quarkus:quarkus-arc` dependency added.
+ """)
+ .withIssueCategory(potentialIssueCategory)
+ .with(guideLink)
+ .withEffort(1)
+ ).performParameterized(event, context, payload)
+ }
+ }
+ }
+ )
+ .endIteration()
+ )
+ .where("packages").matches("(context|event|inject|util)")
+ .withId("jakarta-cdi-to-quarkus-groovy-00020")
+// suggest to replace javax.inject TRANSITIVE dependency if no Quarkus dependency has been already added and 'javax.inject' package is used somewhere in the code
+ .addRule()
+ .when(
+ And.all(
+ JavaClass.references("jakarta.inject.{*}").at(TypeReferenceLocation.ANNOTATION).as("discard"),
+ XmlFile.matchesXpath("/m:project/m:dependencies[count(m:dependency/m:artifactId[contains(., 'jakarta.inject')]) = 0 and count(m:dependency/m:artifactId[contains(., 'quarkus-')]) = 0]")
+ .inFile("pom.xml")
+ .namespace("m", "http://maven.apache.org/POM/4.0.0")
+ .as("dependencies-section")
+ )
+ )
+ .perform(
+ Iteration.over("dependencies-section").perform(
+ new AbstractIterationOperation() {
+ void perform(GraphRewrite event, EvaluationContext context, FileLocationModel payload) {
+ if (matchesProject(event, payload)) {
+ ((Hint) Hint.titled("Remove jakarta.inject:jakarta.inject transitive dependency")
+ .withText("""
+ The application has a transitive `javax.inject:javax.inject` dependency because at least one Java class that imports from the `javax.inject` has been found.
+ The direct dependency injecting `javax.inject:javax.inject` should be identified and replaced with the `io.quarkus:quarkus-arc` dependency.
+ """)
+ .withIssueCategory(potentialIssueCategory)
+ .with(guideLink)
+ .withEffort(1)
+ ).performParameterized(event, context, payload)
+ }
+ }
+ }
+ )
+ .endIteration()
+ )
+ .withId("jakarta-cdi-to-quarkus-groovy-00030")
\ No newline at end of file
diff --git a/rules/rules-reviewed/quarkus/java-ee/jakarta-cdi-to-quarkus.windup.xml b/rules/rules-reviewed/quarkus/java-ee/jakarta-cdi-to-quarkus.windup.xml
new file mode 100644
index 000000000..643ea088d
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/jakarta-cdi-to-quarkus.windup.xml
@@ -0,0 +1,97 @@
+
+
+
+
+ This ruleset gives hints to migrate CDI usage to Quarkus
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dependency `jakarta.enterprise:jakarta.enterprise.cdi-api` has to be replaced with `io.quarkus:quarkus-arc` artifact.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Dependency `jakarta.inject:jakarta.inject-api` has to be replaced with `io.quarkus:quarkus-arc` artifact.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The `beans.xml` descriptor content is ignored and it could be removed from the application.
+ Refer to the guide referenced below to check the supported CDI feature in Quarkus.
+
+
+
+
+
+
+
+
+
+ ANNOTATION
+
+
+
+
+ In Quarkus you can skip the @Produces annotation completely if the producer method is annotated with a scope annotation, a stereotype or a qualifier..
+ This field could be accessed using a `@Named` getter method instead.
+
+
+
+
+
+
+
+
+ ANNOTATION
+
+
+
+
+ The Stateless EJBs can be converted to a cdi bean by replacing the `@Stateless` annotation with a scope eg `@ApplicationScoped`
+
+
+
+
+
+
+
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/cdi-to-quarkus.windup.test.xml b/rules/rules-reviewed/quarkus/java-ee/tests/cdi-to-quarkus.windup.test.xml
index df7b2d8c1..e7825b563 100644
--- a/rules/rules-reviewed/quarkus/java-ee/tests/cdi-to-quarkus.windup.test.xml
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/cdi-to-quarkus.windup.test.xml
@@ -20,18 +20,16 @@
-
+
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/HelloEJB.java b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/HelloEJB.java
new file mode 100644
index 000000000..e53a0805f
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/HelloEJB.java
@@ -0,0 +1,10 @@
+import jakarta.ejb.Stateless;
+
+@Stateless
+public class HelloEJB {
+
+ String createHelloMessage(String name) {
+ return "Hello " + name + "!";
+ }
+
+}
\ No newline at end of file
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/HelloService.java b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/HelloService.java
new file mode 100644
index 000000000..e0d5a88ec
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/HelloService.java
@@ -0,0 +1,12 @@
+package sample;
+
+import jakarta.enterprise.inject.Produces;
+
+
+public class HelloService {
+ @Produces
+ String createHelloMessage(String name) {
+ return "Hello " + name + "!";
+ }
+
+}
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/beans.xml b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/beans.xml
new file mode 100644
index 000000000..24fb02c90
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/beans.xml
@@ -0,0 +1,7 @@
+
+
+
\ No newline at end of file
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/pom.xml b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/pom.xml
new file mode 100644
index 000000000..dd5f9e3c0
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/direct/pom.xml
@@ -0,0 +1,36 @@
+
+ 4.0.0
+ foo
+ bar
+ 999
+
+ 3.10.1
+ 11
+
+
+
+ jakarta.enterprise
+ jakarta.enterprise.cdi-api
+ 4.0.1
+
+
+ jakarta.inject
+ jakarta.inject-api
+ 2.0.1
+
+
+
+
+
+ maven-compiler-plugin
+ ${compiler-plugin.version}
+
+
+ foo
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/HelloService.java b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/HelloService.java
new file mode 100644
index 000000000..e0d5a88ec
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/HelloService.java
@@ -0,0 +1,12 @@
+package sample;
+
+import jakarta.enterprise.inject.Produces;
+
+
+public class HelloService {
+ @Produces
+ String createHelloMessage(String name) {
+ return "Hello " + name + "!";
+ }
+
+}
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/HiWorld.java b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/HiWorld.java
new file mode 100644
index 000000000..156b84f26
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/HiWorld.java
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2015, Red Hat, Inc. and/or its affiliates, and individual
+ * contributors by the @authors tag. See the copyright.txt in the
+ * distribution for a full listing of individual contributors.
+ *
+ * Licensed 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 org.jboss.as.quickstarts.rshelloworld;
+
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+
+/**
+ * A simple REST service which is able to say hello to someone using HelloService Please take a look at the web.xml where JAX-RS
+ * is enabled
+ *
+ * @author gbrey@redhat.com
+ *
+ */
+
+@Path("/")
+public class HiWorld {
+ @Inject
+ InjectedService helloService;
+
+ @GET
+ @Path("/json")
+ @Produces({ "application/json" })
+ public String getHelloWorldJSON() {
+ return "{\"result\":\"" + helloService.createHelloMessage("World") + "\"}";
+ }
+
+ @GET
+ @Path("/xml")
+ @Produces({ "application/xml" })
+ public String getHelloWorldXML() {
+ return "" + helloService.createHelloMessage("World") + "";
+ }
+
+}
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/InjectedService.java b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/InjectedService.java
new file mode 100644
index 000000000..204bdee00
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/InjectedService.java
@@ -0,0 +1,11 @@
+package sample;
+
+
+
+public class InjectedService {
+
+ String createHelloMessage(String name) {
+ return "Hello " + name + "!";
+ }
+
+}
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/pom.xml b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/pom.xml
new file mode 100644
index 000000000..eebd57feb
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/data-jakarta/transitive/pom.xml
@@ -0,0 +1,53 @@
+
+
+
+ 4.0.0
+
+ org.jboss.eap.quickstarts
+ quickstart-parent
+
+ 7.2.0.GA
+ ../pom.xml
+
+ helloworld-rs
+ war
+ Quickstart: helloworld-rs
+ A simple Hello World project that uses JAX-RS
+
+
+
+ Apache License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.html
+ repo
+
+
+
+
+
+
+ jakarta.platform
+ jakarta.jakarta-api
+ 8.0
+ provided
+
+
+
diff --git a/rules/rules-reviewed/quarkus/java-ee/tests/jakarta-cdi-to-quarkus.windup.test.xml b/rules/rules-reviewed/quarkus/java-ee/tests/jakarta-cdi-to-quarkus.windup.test.xml
new file mode 100644
index 000000000..eaba5296c
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/java-ee/tests/jakarta-cdi-to-quarkus.windup.test.xml
@@ -0,0 +1,107 @@
+
+
+ data-jakarta/*
+ ../jakarta-cdi-to-quarkus.windup.xml
+ ../jakarta-cdi-to-quarkus.windup.groovy
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/rules/rules-reviewed/quarkus/quarkus.technology.metadata.xml b/rules/rules-reviewed/quarkus/quarkus.technology.metadata.xml
new file mode 100644
index 000000000..7d7028a62
--- /dev/null
+++ b/rules/rules-reviewed/quarkus/quarkus.technology.metadata.xml
@@ -0,0 +1,6 @@
+
+
+
+ ./api-jars/jakarta.ejb-api-4.0.0.jar
+ ./api-jars/jakarta.enterprise.cdi-api-4.0.0.jar
+
\ No newline at end of file