This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
The following commit(s) were added to refs/heads/main by this push: new 9ec7bc8625 Ref #4379: Groovy DSL native support 9ec7bc8625 is described below commit 9ec7bc8625f68df39b32f6925678282dcbac0e33 Author: Nicolas Filotto <nfilo...@talend.com> AuthorDate: Thu Jan 5 18:45:54 2023 +0100 Ref #4379: Groovy DSL native support --- docs/modules/ROOT/examples/others/groovy-dsl.yml | 6 +- .../pages/reference/extensions/groovy-dsl.adoc | 37 +++- extensions-jvm/pom.xml | 1 - .../groovy-dsl/deployment/pom.xml | 0 .../dsl/groovy/deployment/GroovyDslProcessor.java | 178 +++++++++++++++++ .../deployment/GroovyGeneratedClassBuildItem.java | 27 +-- {extensions-jvm => extensions}/groovy-dsl/pom.xml | 2 +- .../groovy-dsl/runtime/pom.xml | 1 + .../runtime/src/main/doc/limitations.adoc | 18 ++ .../quarkus/dsl/groovy/runtime/Configurer.java | 17 +- .../dsl/groovy/runtime/GroovyDslRecorder.java | 49 +++++ .../groovy/runtime/graal/GroovySubstitutions.java | 83 ++++++++ .../graal/SubstituteGroovyRoutesBuilderLoader.java | 21 +- .../main/resources/META-INF/quarkus-extension.yaml | 3 +- extensions/pom.xml | 1 + integration-tests-jvm/groovy-dsl/pom.xml | 105 ---------- .../camel/quarkus/dsl/groovy/GroovyDslTest.java | 49 ----- integration-tests-jvm/pom.xml | 1 - integration-tests/groovy-dsl/pom.xml | 217 +++++++++++++++++++++ .../quarkus/dsl/groovy/GroovyDslResource.java | 58 ++++-- .../src/main/resources/application.properties | 2 +- .../src/main/resources/routes/my-routes.groovy | 8 +- .../routes-with-components-configuration.groovy | 20 +- .../routes-with-dataformats-configuration.groovy | 23 ++- .../routes/routes-with-endpoint-dsl.groovy | 9 +- .../routes/routes-with-error-handler.groovy | 11 +- .../routes-with-languages-configuration.groovy | 17 +- .../camel/quarkus/dsl/groovy/GroovyDslIT.java | 11 +- .../camel/quarkus/dsl/groovy/GroovyDslTest.java | 59 ++++++ integration-tests/pom.xml | 1 + tooling/scripts/test-categories.yaml | 1 + 31 files changed, 810 insertions(+), 226 deletions(-) diff --git a/docs/modules/ROOT/examples/others/groovy-dsl.yml b/docs/modules/ROOT/examples/others/groovy-dsl.yml index 062e598158..606db51927 100644 --- a/docs/modules/ROOT/examples/others/groovy-dsl.yml +++ b/docs/modules/ROOT/examples/others/groovy-dsl.yml @@ -2,11 +2,11 @@ # This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page cqArtifactId: camel-quarkus-groovy-dsl cqArtifactIdBase: groovy-dsl -cqNativeSupported: false -cqStatus: Preview +cqNativeSupported: true +cqStatus: Stable cqDeprecated: false cqJvmSince: 1.8.0 -cqNativeSince: n/a +cqNativeSince: 2.16.0 cqCamelPartName: groovy-dsl cqCamelPartTitle: Groovy Dsl cqCamelPartDescription: Camel DSL with Groovy diff --git a/docs/modules/ROOT/pages/reference/extensions/groovy-dsl.adoc b/docs/modules/ROOT/pages/reference/extensions/groovy-dsl.adoc index 43af62e00f..b5b1d0c9e4 100644 --- a/docs/modules/ROOT/pages/reference/extensions/groovy-dsl.adoc +++ b/docs/modules/ROOT/pages/reference/extensions/groovy-dsl.adoc @@ -4,17 +4,17 @@ = Groovy DSL :linkattrs: :cq-artifact-id: camel-quarkus-groovy-dsl -:cq-native-supported: false -:cq-status: Preview -:cq-status-deprecation: Preview +:cq-native-supported: true +:cq-status: Stable +:cq-status-deprecation: Stable :cq-description: Support for parsing Groovy route definitions at runtime :cq-deprecated: false :cq-jvm-since: 1.8.0 -:cq-native-since: n/a +:cq-native-since: 2.16.0 ifeval::[{doc-show-badges} == true] [.badges] -[.badge-key]##JVM since##[.badge-supported]##1.8.0## [.badge-key]##Native##[.badge-unsupported]##unsupported## +[.badge-key]##JVM since##[.badge-supported]##1.8.0## [.badge-key]##Native since##[.badge-supported]##2.16.0## endif::[] Support for parsing Groovy route definitions at runtime @@ -29,6 +29,10 @@ Please refer to the above link for usage and configuration details. [id="extensions-groovy-dsl-maven-coordinates"] == Maven coordinates +https://{link-quarkus-code-generator}/?extension-search=camel-quarkus-groovy-dsl[Create a new project with this extension on {link-quarkus-code-generator}, window="_blank"] + +Or add the coordinates to your existing project: + [source,xml] ---- <dependency> @@ -39,3 +43,26 @@ Please refer to the above link for usage and configuration details. ifeval::[{doc-show-user-guide-link} == true] Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications. endif::[] + +[id="extensions-groovy-dsl-camel-quarkus-limitations"] +== Camel Quarkus limitations + +The Groovy extensions are not supported which means that the extensions defined in the Camel project are ignored, more details in https://github.com/apache/camel-quarkus/issues/4384[Groovy DSL - Add support of Groovy extensions issue #4384]. + +In case of native compilation, for some specific use cases like the following one, it could be needed to add the flag `--report-unsupported-elements-at-runtime` to prevent compilation error of type `DeletedElementException: Unsupported method java.lang.Class.registerNatives() is reachable`. + +[source,groovy] +---- +import org.apache.camel.component.seda.SedaComponent + +camel { + components { + mySeda(SedaComponent) { // <1> + // rest of the closure here + } + } +} +// rest of the Groovy script +---- +<1> Requires the flag `--report-unsupported-elements-at-runtime` to be added to the build command for native compilation. + diff --git a/extensions-jvm/pom.xml b/extensions-jvm/pom.xml index 2902ad693e..01ff26c757 100644 --- a/extensions-jvm/pom.xml +++ b/extensions-jvm/pom.xml @@ -67,7 +67,6 @@ <module>google-functions</module> <module>google-secret-manager</module> <module>groovy</module> - <module>groovy-dsl</module> <module>guava-eventbus</module> <module>hashicorp-vault</module> <module>hbase</module> diff --git a/extensions-jvm/groovy-dsl/deployment/pom.xml b/extensions/groovy-dsl/deployment/pom.xml similarity index 100% rename from extensions-jvm/groovy-dsl/deployment/pom.xml rename to extensions/groovy-dsl/deployment/pom.xml diff --git a/extensions/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyDslProcessor.java b/extensions/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyDslProcessor.java new file mode 100644 index 0000000000..c97336d80e --- /dev/null +++ b/extensions/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyDslProcessor.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 org.apache.camel.quarkus.dsl.groovy.deployment; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.annotations.ExecutionTime; +import io.quarkus.deployment.annotations.Record; +import io.quarkus.deployment.builditem.FeatureBuildItem; +import io.quarkus.deployment.builditem.GeneratedClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.pkg.builditem.CurateOutcomeBuildItem; +import io.quarkus.deployment.pkg.steps.NativeBuild; +import io.quarkus.maven.dependency.ResolvedDependency; +import io.quarkus.paths.PathCollection; +import io.quarkus.runtime.RuntimeValue; +import org.apache.camel.CamelContext; +import org.apache.camel.quarkus.core.deployment.main.CamelMainHelper; +import org.apache.camel.quarkus.core.deployment.spi.CamelContextBuildItem; +import org.apache.camel.quarkus.dsl.groovy.runtime.Configurer; +import org.apache.camel.quarkus.dsl.groovy.runtime.GroovyDslRecorder; +import org.apache.camel.spi.Resource; +import org.apache.camel.util.FileUtil; +import org.apache.camel.util.IOHelper; +import org.codehaus.groovy.control.CompilationUnit; +import org.codehaus.groovy.control.CompilerConfiguration; +import org.codehaus.groovy.control.Phases; +import org.codehaus.groovy.tools.GroovyClass; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GroovyDslProcessor { + + private static final Logger LOG = LoggerFactory.getLogger(GroovyDslProcessor.class); + private static final String PACKAGE_NAME = "org.apache.camel.quarkus.dsl.groovy.generated"; + private static final Pattern IMPORT_PATTERN = Pattern.compile("import .*"); + private static final String FILE_FORMAT = "package %s\n" + + "%s\n" + + "@groovy.transform.InheritConstructors \n" + + "class %s extends %s {\n" + + " void configure(){ \n" + + " %s\n" + + " }\n" + + "}"; + private static final String FEATURE = "camel-groovy-dsl"; + + @BuildStep + FeatureBuildItem feature() { + return new FeatureBuildItem(FEATURE); + } + + @BuildStep(onlyIf = NativeBuild.class) + void compileScriptsAOT(BuildProducer<GeneratedClassBuildItem> generatedClass, + BuildProducer<ReflectiveClassBuildItem> reflectiveClass, + BuildProducer<GroovyGeneratedClassBuildItem> generatedGroovyClass, + CurateOutcomeBuildItem curateOutcomeBuildItem) throws Exception { + LOG.debug("Loading .groovy resources"); + Map<String, Resource> nameToResource = new HashMap<>(); + CompilationUnit unit = new CompilationUnit(); + CamelMainHelper.forEachMatchingResource( + resource -> { + if (!resource.getLocation().endsWith(".groovy")) { + return; + } + try (InputStream is = resource.getInputStream()) { + String name = determineName(resource); + String fqn = String.format("%s.%s", PACKAGE_NAME, name); + unit.addSource(fqn, toGroovyClass(name, IOHelper.loadText(is))); + nameToResource.put(fqn, resource); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + if (nameToResource.isEmpty()) { + return; + } + CompilerConfiguration cc = new CompilerConfiguration(); + cc.setClasspathList( + curateOutcomeBuildItem.getApplicationModel().getDependencies().stream() + .map(ResolvedDependency::getResolvedPaths) + .flatMap(PathCollection::stream) + .map(Objects::toString) + .collect(Collectors.toList())); + unit.configure(cc); + unit.compile(Phases.CLASS_GENERATION); + for (GroovyClass clazz : unit.getClasses()) { + String className = clazz.getName(); + generatedClass.produce(new GeneratedClassBuildItem(true, className, clazz.getBytes())); + if (nameToResource.containsKey(className)) { + reflectiveClass.produce(new ReflectiveClassBuildItem(false, false, className)); + generatedGroovyClass + .produce(new GroovyGeneratedClassBuildItem(className, nameToResource.get(className).getLocation())); + } + } + } + + @BuildStep(onlyIf = NativeBuild.class) + @Record(value = ExecutionTime.STATIC_INIT) + void registerRoutesBuilder(List<GroovyGeneratedClassBuildItem> classes, + CamelContextBuildItem context, + GroovyDslRecorder recorder) throws Exception { + RuntimeValue<CamelContext> camelContext = context.getCamelContext(); + for (GroovyGeneratedClassBuildItem clazz : classes) { + recorder.registerRoutesBuilder(camelContext, clazz.getName(), clazz.getLocation()); + } + } + + // To put it back once the Groovy extensions will be supported (https://github.com/apache/camel-quarkus/issues/4384) + // @BuildStep + // void registerNativeImageResources(BuildProducer<ServiceProviderBuildItem> serviceProvider) { + // serviceProvider + // .produce(ServiceProviderBuildItem.allProvidersFromClassPath("org.codehaus.groovy.runtime.ExtensionModule")); + // } + + private static String determineName(Resource resource) { + String str = FileUtil.onlyName(resource.getLocation(), true); + StringBuilder sb = new StringBuilder(); + for (int i = 0, length = str.length(); i < length; i++) { + char c = str.charAt(i); + if ((i == 0 && Character.isJavaIdentifierStart(c)) || (i > 0 && Character.isJavaIdentifierPart(c))) { + sb.append(c); + } else { + sb.append((int) c); + } + } + return sb.toString(); + } + + /** + * Convert a Groovy script into a Groovy class to be able to compile it. + * + * @param name the name of the Groovy class + * @param contentResource the content of the Groovy script + * @return the content of the corresponding Groovy class. + */ + private static String toGroovyClass(String name, String contentResource) { + List<String> imports = new ArrayList<>(); + imports.add("import org.apache.camel.*"); + imports.add("import org.apache.camel.spi.*"); + Matcher m = IMPORT_PATTERN.matcher(contentResource); + int beginIndex = 0; + while (m.find()) { + imports.add(m.group()); + beginIndex = m.end(); + } + if (beginIndex > 0) { + contentResource = contentResource.substring(beginIndex); + } + return String.format( + FILE_FORMAT, PACKAGE_NAME, String.join("\n", imports), name, Configurer.class.getName(), contentResource); + } +} diff --git a/extensions-jvm/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyDslProcessor.java b/extensions/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyGeneratedClassBuildItem.java similarity index 59% rename from extensions-jvm/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyDslProcessor.java rename to extensions/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyGeneratedClassBuildItem.java index de170e888d..2dbe334a7f 100644 --- a/extensions-jvm/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyDslProcessor.java +++ b/extensions/groovy-dsl/deployment/src/main/java/org/apache/camel/quarkus/dsl/groovy/deployment/GroovyGeneratedClassBuildItem.java @@ -14,24 +14,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.apache.camel.quarkus.dsl.groovy.deployment; -import io.quarkus.deployment.annotations.BuildStep; -import io.quarkus.deployment.builditem.FeatureBuildItem; -import io.quarkus.deployment.pkg.steps.NativeBuild; +import io.quarkus.builder.item.MultiBuildItem; + +public final class GroovyGeneratedClassBuildItem extends MultiBuildItem { -public class GroovyDslProcessor { - private static final String FEATURE = "camel-groovy-dsl"; + final String name; + final String location; + + public GroovyGeneratedClassBuildItem(String name, String location) { + this.name = name; + this.location = location; + } - @BuildStep - FeatureBuildItem feature() { - return new FeatureBuildItem(FEATURE); + public String getName() { + return this.name; } - @BuildStep(onlyIf = NativeBuild.class) - void nativeUnsupported() { - throw new RuntimeException("The " + FEATURE + " extension is not supported in native mode " - + "as loading Groovy code at runtime is not supported on GraalVM"); + public String getLocation() { + return location; } } diff --git a/extensions-jvm/groovy-dsl/pom.xml b/extensions/groovy-dsl/pom.xml similarity index 96% rename from extensions-jvm/groovy-dsl/pom.xml rename to extensions/groovy-dsl/pom.xml index 5c5dcc990f..1c8867f8a4 100644 --- a/extensions-jvm/groovy-dsl/pom.xml +++ b/extensions/groovy-dsl/pom.xml @@ -21,7 +21,7 @@ <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-extensions-jvm</artifactId> + <artifactId>camel-quarkus-extensions</artifactId> <version>2.16.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/extensions-jvm/groovy-dsl/runtime/pom.xml b/extensions/groovy-dsl/runtime/pom.xml similarity index 98% rename from extensions-jvm/groovy-dsl/runtime/pom.xml rename to extensions/groovy-dsl/runtime/pom.xml index fe38581b00..d41a33af8e 100644 --- a/extensions-jvm/groovy-dsl/runtime/pom.xml +++ b/extensions/groovy-dsl/runtime/pom.xml @@ -32,6 +32,7 @@ <properties> <camel.quarkus.jvmSince>1.8.0</camel.quarkus.jvmSince> + <camel.quarkus.nativeSince>2.16.0</camel.quarkus.nativeSince> </properties> <dependencies> diff --git a/extensions/groovy-dsl/runtime/src/main/doc/limitations.adoc b/extensions/groovy-dsl/runtime/src/main/doc/limitations.adoc new file mode 100644 index 0000000000..b1a77c234a --- /dev/null +++ b/extensions/groovy-dsl/runtime/src/main/doc/limitations.adoc @@ -0,0 +1,18 @@ +The Groovy extensions are not supported which means that the extensions defined in the Camel project are ignored, more details in https://github.com/apache/camel-quarkus/issues/4384[Groovy DSL - Add support of Groovy extensions issue #4384]. + +In case of native compilation, for some specific use cases like the following one, it could be needed to add the flag `--report-unsupported-elements-at-runtime` to prevent compilation error of type `DeletedElementException: Unsupported method java.lang.Class.registerNatives() is reachable`. + +[source,groovy] +---- +import org.apache.camel.component.seda.SedaComponent + +camel { + components { + mySeda(SedaComponent) { // <1> + // rest of the closure here + } + } +} +// rest of the Groovy script +---- +<1> Requires the flag `--report-unsupported-elements-at-runtime` to be added to the build command for native compilation. diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/Configurer.java similarity index 64% copy from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy copy to extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/Configurer.java index f0136d044a..c892ef1a42 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/Configurer.java @@ -14,6 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file +package org.apache.camel.quarkus.dsl.groovy.runtime; + +import org.apache.camel.builder.endpoint.EndpointRouteBuilder; +import org.apache.camel.dsl.groovy.common.GroovyDSL; + +public abstract class Configurer extends GroovyDSL { + + // The constructor needs to remain public to be accessible from a Groovy Script + public Configurer(EndpointRouteBuilder builder) { + super(builder); + } + + public abstract void configure(); +} diff --git a/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/GroovyDslRecorder.java b/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/GroovyDslRecorder.java new file mode 100644 index 0000000000..95d9904a41 --- /dev/null +++ b/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/GroovyDslRecorder.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 org.apache.camel.quarkus.dsl.groovy.runtime; + +import java.lang.reflect.Constructor; + +import io.quarkus.runtime.RuntimeValue; +import io.quarkus.runtime.annotations.Recorder; +import org.apache.camel.CamelContext; +import org.apache.camel.RuntimeCamelException; +import org.apache.camel.builder.endpoint.EndpointRouteBuilder; +import org.apache.camel.support.ResourceHelper; + +@Recorder +public class GroovyDslRecorder { + public void registerRoutesBuilder(RuntimeValue<CamelContext> camelContext, String className, String location) + throws Exception { + Constructor<? extends Configurer> constructor = (Constructor<? extends Configurer>) Class.forName(className) + .getDeclaredConstructor(EndpointRouteBuilder.class); + camelContext.getValue().addRoutes( + new EndpointRouteBuilder() { + + @Override + public void configure() throws Exception { + setCamelContext(camelContext.getValue()); + setResource(ResourceHelper.fromString(location, "")); + try { + constructor.newInstance(this).configure(); + } catch (Exception e) { + throw new RuntimeCamelException("Cannot create instance of class: " + className, e); + } + } + }); + } +} diff --git a/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/graal/GroovySubstitutions.java b/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/graal/GroovySubstitutions.java new file mode 100644 index 0000000000..3ddba6d540 --- /dev/null +++ b/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/graal/GroovySubstitutions.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 org.apache.camel.quarkus.dsl.groovy.runtime.graal; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MutableCallSite; +import java.lang.reflect.Constructor; + +import com.oracle.svm.core.annotate.Delete; +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import org.codehaus.groovy.control.ParserPluginFactory; + +final class GroovySubstitutions { +} + +@TargetClass(className = "org.codehaus.groovy.vmplugin.v8.IndyInterface") +final class SubstituteIndyInterface { + + @Substitute + protected static void invalidateSwitchPoints() { + throw new UnsupportedOperationException("invalidateSwitchPoints is not supported"); + } + + @Substitute + public static Object fromCache(MutableCallSite callSite, Class<?> sender, String methodName, int callID, + Boolean safeNavigation, Boolean thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) { + throw new UnsupportedOperationException("fromCache is not supported"); + } +} + +@TargetClass(className = "org.codehaus.groovy.control.SourceUnit") +final class SubstituteSourceUnit { + + @Substitute + public void convert() { + throw new UnsupportedOperationException("convert is not supported"); + } +} + +@TargetClass(className = "org.codehaus.groovy.vmplugin.v8.Java8") +final class SubstituteJava8 { + + @Substitute + private static Constructor<MethodHandles.Lookup> getLookupConstructor() { + throw new UnsupportedOperationException("getLookupConstructor is not supported"); + } +} + +@TargetClass(className = "org.codehaus.groovy.antlr.AntlrParserPlugin") +@Delete +final class SubstituteAntlrParserPlugin { + +} + +@TargetClass(className = "org.codehaus.groovy.antlr.AntlrParserPluginFactory") +@Delete +final class SubstituteAntlrParserPluginFactory { + +} + +@TargetClass(className = "org.codehaus.groovy.control.ParserPluginFactory") +final class SubstituteParserPluginFactory { + + @Substitute + public static ParserPluginFactory antlr2() { + throw new UnsupportedOperationException("antlr2 is not supported"); + } +} diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/graal/SubstituteGroovyRoutesBuilderLoader.java similarity index 59% copy from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy copy to extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/graal/SubstituteGroovyRoutesBuilderLoader.java index f0136d044a..d2880aaa95 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/extensions/groovy-dsl/runtime/src/main/java/org/apache/camel/quarkus/dsl/groovy/runtime/graal/SubstituteGroovyRoutesBuilderLoader.java @@ -14,6 +14,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file +package org.apache.camel.quarkus.dsl.groovy.runtime.graal; + +import java.io.Reader; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import org.apache.camel.builder.endpoint.EndpointRouteBuilder; +import org.apache.camel.dsl.groovy.GroovyRoutesBuilderLoader; + +@TargetClass(GroovyRoutesBuilderLoader.class) +final class SubstituteGroovyRoutesBuilderLoader { + + @Substitute + protected void doLoadEndpointRouteBuilder(Reader reader, EndpointRouteBuilder builder) { + // Do nothing + } + +} diff --git a/extensions-jvm/groovy-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/groovy-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml similarity index 97% rename from extensions-jvm/groovy-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml rename to extensions/groovy-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml index 0635a7e050..3310fa3906 100644 --- a/extensions-jvm/groovy-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml +++ b/extensions/groovy-dsl/runtime/src/main/resources/META-INF/quarkus-extension.yaml @@ -24,9 +24,8 @@ name: "Camel Groovy DSL" description: "Support for parsing Groovy route definitions at runtime" metadata: - unlisted: true guide: "https://camel.apache.org/camel-quarkus/latest/reference/extensions/groovy-dsl.html" categories: - "integration" status: - - "preview" + - "stable" diff --git a/extensions/pom.xml b/extensions/pom.xml index 98e2d02638..f548467277 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -117,6 +117,7 @@ <module>google-storage</module> <module>graphql</module> <module>grok</module> + <module>groovy-dsl</module> <module>grpc</module> <module>gson</module> <module>hazelcast</module> diff --git a/integration-tests-jvm/groovy-dsl/pom.xml b/integration-tests-jvm/groovy-dsl/pom.xml deleted file mode 100644 index 6baeb851b9..0000000000 --- a/integration-tests-jvm/groovy-dsl/pom.xml +++ /dev/null @@ -1,105 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF 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. - ---> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-build-parent-it</artifactId> - <version>2.16.0-SNAPSHOT</version> - <relativePath>../../poms/build-parent-it/pom.xml</relativePath> - </parent> - - <artifactId>camel-quarkus-integration-test-groovy-dsl</artifactId> - <name>Camel Quarkus :: Integration Tests :: Groovy DSL</name> - <description>Integration tests for Camel Groovy DSL extension</description> - - <dependencies> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-groovy-dsl</artifactId> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-direct</artifactId> - </dependency> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-resteasy-jsonb</artifactId> - </dependency> - - <!-- test dependencies --> - <dependency> - <groupId>io.quarkus</groupId> - <artifactId>quarkus-junit5</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>io.rest-assured</groupId> - <artifactId>rest-assured</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.assertj</groupId> - <artifactId>assertj-core</artifactId> - <scope>test</scope> - </dependency> - </dependencies> - - <profiles> - <profile> - <id>virtualDependencies</id> - <activation> - <property> - <name>!noVirtualDependencies</name> - </property> - </activation> - <dependencies> - <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-direct-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.apache.camel.quarkus</groupId> - <artifactId>camel-quarkus-groovy-dsl-deployment</artifactId> - <version>${project.version}</version> - <type>pom</type> - <scope>test</scope> - <exclusions> - <exclusion> - <groupId>*</groupId> - <artifactId>*</artifactId> - </exclusion> - </exclusions> - </dependency> - </dependencies> - </profile> - </profiles> - -</project> diff --git a/integration-tests-jvm/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslTest.java b/integration-tests-jvm/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslTest.java deleted file mode 100644 index 67fca5acb0..0000000000 --- a/integration-tests-jvm/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF 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 org.apache.camel.quarkus.dsl.groovy; - -import javax.ws.rs.core.MediaType; - -import io.quarkus.test.junit.QuarkusTest; -import io.restassured.RestAssured; -import io.restassured.path.json.JsonPath; -import org.apache.camel.dsl.groovy.GroovyRoutesBuilderLoader; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -@QuarkusTest -public class GroovyDslTest { - @Test - public void testMainInstanceWithJavaRoutes() { - JsonPath p = RestAssured.given() - .accept(MediaType.APPLICATION_JSON) - .get("/test/main/describe") - .then() - .statusCode(200) - .extract() - .body() - .jsonPath(); - - assertThat(p.getString("routes-builder-loader")) - .isEqualTo(GroovyRoutesBuilderLoader.class.getName()); - assertThat(p.getList("routeBuilders", String.class)) - .isEmpty(); - assertThat(p.getList("routes", String.class)) - .contains("my-groovy-route"); - } -} diff --git a/integration-tests-jvm/pom.xml b/integration-tests-jvm/pom.xml index 119130ec32..b6fdee38d3 100644 --- a/integration-tests-jvm/pom.xml +++ b/integration-tests-jvm/pom.xml @@ -66,7 +66,6 @@ <module>google-functions</module> <module>google-secret-manager</module> <module>groovy</module> - <module>groovy-dsl</module> <module>guava-eventbus</module> <module>hashicorp-vault</module> <module>hbase</module> diff --git a/integration-tests/groovy-dsl/pom.xml b/integration-tests/groovy-dsl/pom.xml new file mode 100644 index 0000000000..693767cf44 --- /dev/null +++ b/integration-tests/groovy-dsl/pom.xml @@ -0,0 +1,217 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF 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. + +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-build-parent-it</artifactId> + <version>2.16.0-SNAPSHOT</version> + <relativePath>../../poms/build-parent-it/pom.xml</relativePath> + </parent> + + <artifactId>camel-quarkus-integration-test-groovy-dsl</artifactId> + <name>Camel Quarkus :: Integration Tests :: Groovy DSL</name> + <description>Integration tests for Camel Groovy DSL extension</description> + + <dependencies> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-groovy-dsl</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-seda</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-jackson</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-bean</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-timer</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-log</artifactId> + </dependency> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-resteasy-jsonb</artifactId> + </dependency> + + <!-- test dependencies --> + <dependency> + <groupId>io.quarkus</groupId> + <artifactId>quarkus-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>io.rest-assured</groupId> + <artifactId>rest-assured</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-core</artifactId> + <scope>test</scope> + </dependency> + </dependencies> + + <profiles> + <profile> + <id>virtualDependencies</id> + <activation> + <property> + <name>!noVirtualDependencies</name> + </property> + </activation> + <dependencies> + <!-- The following dependencies guarantee that this module is built after them. You can update them by running `mvn process-resources -Pformat -N` from the source tree root directory --> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-bean-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-direct-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-groovy-dsl-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-jackson-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-log-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-seda-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.apache.camel.quarkus</groupId> + <artifactId>camel-quarkus-timer-deployment</artifactId> + <version>${project.version}</version> + <type>pom</type> + <scope>test</scope> + <exclusions> + <exclusion> + <groupId>*</groupId> + <artifactId>*</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + </profile> + <profile> + <id>native</id> + <activation> + <property> + <name>native</name> + </property> + </activation> + <properties> + <quarkus.package.type>native</quarkus.package.type> + </properties> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> + +</project> diff --git a/integration-tests-jvm/groovy-dsl/src/main/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslResource.java b/integration-tests/groovy-dsl/src/main/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslResource.java similarity index 51% rename from integration-tests-jvm/groovy-dsl/src/main/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslResource.java rename to integration-tests/groovy-dsl/src/main/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslResource.java index 6ccb0cb719..863953b844 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslResource.java +++ b/integration-tests/groovy-dsl/src/main/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslResource.java @@ -16,45 +16,67 @@ */ package org.apache.camel.quarkus.dsl.groovy; +import java.util.stream.Collectors; + import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; -import javax.json.Json; -import javax.json.JsonArrayBuilder; -import javax.json.JsonObject; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.Route; import org.apache.camel.dsl.groovy.GroovyRoutesBuilderLoader; import org.apache.camel.quarkus.main.CamelMain; import org.apache.camel.spi.RoutesBuilderLoader; -@Path("/test") +@Path("/groovy-dsl") @ApplicationScoped public class GroovyDslResource { @Inject CamelMain main; - @Path("/main/describe") + @Inject + ProducerTemplate producerTemplate; + + @Path("/main/groovyRoutesBuilderLoader") @GET - @Produces(MediaType.APPLICATION_JSON) - public JsonObject describeMain() { + @Produces(MediaType.TEXT_PLAIN) + public String groovyRoutesBuilder() { final ExtendedCamelContext camelContext = main.getCamelContext().adapt(ExtendedCamelContext.class); + return camelContext.getBootstrapFactoryFinder(RoutesBuilderLoader.FACTORY_PATH) + .findClass(GroovyRoutesBuilderLoader.EXTENSION).get().getName(); + } - JsonArrayBuilder routeBuilders = Json.createArrayBuilder(); - main.configure().getRoutesBuilders().forEach(builder -> routeBuilders.add(builder.getClass().getName())); + @Path("/main/routeBuilders") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String routeBuilders() { + return main.configure().getRoutesBuilders().stream() + .map(rb -> rb.getClass().getSimpleName()) + .sorted() + .collect(Collectors.joining(",")); + } - JsonArrayBuilder routes = Json.createArrayBuilder(); - main.getCamelContext().getRoutes().forEach(route -> routes.add(route.getId())); + @Path("/main/routes") + @GET + @Produces(MediaType.TEXT_PLAIN) + public String routes() { + return main.getCamelContext().getRoutes().stream() + .map(Route::getId) + .sorted() + .collect(Collectors.joining(",")); + } - return Json.createObjectBuilder() - .add("routes-builder-loader", - camelContext.getBootstrapFactoryFinder(RoutesBuilderLoader.FACTORY_PATH) - .findClass(GroovyRoutesBuilderLoader.EXTENSION).get().getName()) - .add("routeBuilders", routeBuilders) - .add("routes", routes) - .build(); + @POST + @Path("/hello") + @Consumes(MediaType.TEXT_PLAIN) + @Produces(MediaType.TEXT_PLAIN) + public String hello(String message) { + return producerTemplate.requestBody("direct:groovyHello", message, String.class); } } diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/application.properties b/integration-tests/groovy-dsl/src/main/resources/application.properties similarity index 93% rename from integration-tests-jvm/groovy-dsl/src/main/resources/application.properties rename to integration-tests/groovy-dsl/src/main/resources/application.properties index 2d233c8360..7ab2bf28e3 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/application.properties +++ b/integration-tests/groovy-dsl/src/main/resources/application.properties @@ -18,4 +18,4 @@ # # Main # -camel.main.routes-include-pattern = classpath:routes/my-routes.groovy +camel.main.routes-include-pattern = classpath:routes/*.groovy diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/integration-tests/groovy-dsl/src/main/resources/routes/my-routes.groovy similarity index 74% copy from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy copy to integration-tests/groovy-dsl/src/main/resources/routes/my-routes.groovy index f0136d044a..e1e7cb2972 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/integration-tests/groovy-dsl/src/main/resources/routes/my-routes.groovy @@ -14,6 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file +from('direct:groovyHello') + .id('my-groovy-route') + .setBody().simple('Hello ${body} from Groovy!') + // Extensions are not supported due to https://github.com/apache/camel-quarkus/issues/4384 + // .setBody { e -> "Hello " + e.in.body + " from Groovy!" } diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-components-configuration.groovy similarity index 73% copy from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy copy to integration-tests/groovy-dsl/src/main/resources/routes/routes-with-components-configuration.groovy index f0136d044a..c32538db86 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-components-configuration.groovy @@ -14,6 +14,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file + +camel { + components { + seda { + // set value as method + queueSize 1234 + + // set value as property + concurrentConsumers = 12 + } + } +} + + +from('timer:tick') + .id('routes-with-components-configuration') + .to('log:info') diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-dataformats-configuration.groovy similarity index 64% copy from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy copy to integration-tests/groovy-dsl/src/main/resources/routes/routes-with-dataformats-configuration.groovy index f0136d044a..127dba3550 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-dataformats-configuration.groovy @@ -14,6 +14,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file + +import org.apache.camel.component.jackson.JacksonDataFormat + +camel { + dataFormats { + dataFormat("jackson") { + unmarshalType = Map.class + prettyPrint = true + } + dataFormat("my-jackson", JacksonDataFormat) { + unmarshalType = String.class + prettyPrint = false + } + } +} + + +from('timer:tick') + .id('routes-with-dataformats-configuration') + .to('log:info') diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-endpoint-dsl.groovy similarity index 87% copy from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy copy to integration-tests/groovy-dsl/src/main/resources/routes/routes-with-endpoint-dsl.groovy index f0136d044a..18f2b7b9ce 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-endpoint-dsl.groovy @@ -14,6 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file +def f = timer('tick').period('1s') +def t = log('info') + +from(f) + .id('routes-with-endpoint-dsl') + .to(t) \ No newline at end of file diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-error-handler.groovy similarity index 82% copy from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy copy to integration-tests/groovy-dsl/src/main/resources/routes/routes-with-error-handler.groovy index f0136d044a..406269a016 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-error-handler.groovy @@ -14,6 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file + +onException(IllegalArgumentException.class) + .id('my-on-exception') + .to('log:exception') + +from('timer:tick') + .id('routes-with-error-handler') + .to('log:info') \ No newline at end of file diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-languages-configuration.groovy similarity index 78% copy from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy copy to integration-tests/groovy-dsl/src/main/resources/routes/routes-with-languages-configuration.groovy index f0136d044a..144249b8ae 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/integration-tests/groovy-dsl/src/main/resources/routes/routes-with-languages-configuration.groovy @@ -14,6 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file + +camel { + languages { + bean { + beanType = String.class + method = "toUpperCase" + } + } +} + + +from('timer:tick') + .id('routes-with-languages-configuration') + .to('log:info') \ No newline at end of file diff --git a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy b/integration-tests/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslIT.java similarity index 82% rename from integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy rename to integration-tests/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslIT.java index f0136d044a..50fb8bd47d 100644 --- a/integration-tests-jvm/groovy-dsl/src/main/resources/routes/my-routes.groovy +++ b/integration-tests/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslIT.java @@ -14,6 +14,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -from('direct:start') - .id('my-groovy-route') - .log('Hello Groovy !!!') \ No newline at end of file +package org.apache.camel.quarkus.dsl.groovy; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +class GroovyDslIT extends GroovyDslTest { + +} diff --git a/integration-tests/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslTest.java b/integration-tests/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslTest.java new file mode 100644 index 0000000000..87e065f256 --- /dev/null +++ b/integration-tests/groovy-dsl/src/test/java/org/apache/camel/quarkus/dsl/groovy/GroovyDslTest.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 org.apache.camel.quarkus.dsl.groovy; + +import io.quarkus.test.junit.QuarkusTest; +import io.restassured.RestAssured; +import org.apache.camel.dsl.groovy.GroovyRoutesBuilderLoader; +import org.hamcrest.CoreMatchers; +import org.junit.jupiter.api.Test; + +@QuarkusTest +class GroovyDslTest { + + @Test + void groovyHello() { + RestAssured.given() + .body("John Smith") + .post("/groovy-dsl/hello") + .then() + .statusCode(200) + .body(CoreMatchers.is("Hello John Smith from Groovy!")); + } + + @Test + void testMainInstanceWithJavaRoutes() { + RestAssured.given() + .get("/groovy-dsl/main/groovyRoutesBuilderLoader") + .then() + .statusCode(200) + .body(CoreMatchers.is(GroovyRoutesBuilderLoader.class.getName())); + + RestAssured.given() + .get("/groovy-dsl/main/routeBuilders") + .then() + .statusCode(200) + .body(CoreMatchers.is("")); + + RestAssured.given() + .get("/groovy-dsl/main/routes") + .then() + .statusCode(200) + .body(CoreMatchers.is( + "my-groovy-route,routes-with-components-configuration,routes-with-dataformats-configuration,routes-with-endpoint-dsl,routes-with-error-handler,routes-with-languages-configuration")); + } +} diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 6cec5ae466..061f0adea1 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -104,6 +104,7 @@ <module>google-storage</module> <module>graphql</module> <module>grok</module> + <module>groovy-dsl</module> <module>grpc</module> <module>hazelcast</module> <module>headersmap</module> diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml index e81a8e5052..c0c776976d 100644 --- a/tooling/scripts/test-categories.yaml +++ b/tooling/scripts/test-categories.yaml @@ -204,6 +204,7 @@ group-13: - fhir - github - google + - groovy-dsl - jira - java-joor-dsl - js-dsl