@@ -100,12 +84,6 @@
org.apache.camel:camel-core-languages
-
-
- META-INF/services/org/apache/camel/language/simple-no-file
- ${project.basedir}/src/main/resources/META-INF/services/org/apache/camel/language/simple-no-file
-
-
diff --git a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleNoFileLanguage.java b/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleNoFileLanguage.java
deleted file mode 100644
index 9829975440..0000000000
--- a/core/camel-core-languages/src/main/java/org/apache/camel/language/simple/SimpleNoFileLanguage.java
+++ /dev/null
@@ -1,32 +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.language.simple;
-
-import org.apache.camel.spi.annotations.Language;
-
-/**
- * The {@link SimpleLanguage} but without support for using the file based functions. This is used in some special
- * situations with EIPs such as poll/pollEnrich. This language is not exposed as a public standard language and are only
- * intended for internal use.
- */
-@Language(value = "simple-no-file", functionsClass = SimpleConstants.class)
-public final class SimpleNoFileLanguage extends SimpleLanguage {
-
- public SimpleNoFileLanguage() {
- super(true);
- }
-}
diff --git a/core/camel-core-languages/src/main/resources/META-INF/services/org/apache/camel/language/simple-no-file b/core/camel-core-languages/src/main/resources/META-INF/services/org/apache/camel/language/simple-no-file
index 0c9b7e9cec..faf3f1aedd 100644
--- a/core/camel-core-languages/src/main/resources/META-INF/services/org/apache/camel/language/simple-no-file
+++ b/core/camel-core-languages/src/main/resources/META-INF/services/org/apache/camel/language/simple-no-file
@@ -1 +1,24 @@
+#
+# 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.
+#
+# Camel-karaf specific: Apache Camel intentionally ships no service file for this
+# language, because DefaultLanguageResolver resolves the name through a hardcoded
+# branch instead. OsgiLanguageResolver has no such branch and looks the language up
+# in the OSGi service registry, so without this entry "simple-no-file" cannot be
+# resolved in Karaf and poll/pollEnrich with a simple expression fails with
+# NoSuchLanguageException. Keep this file across Camel upgrades. See issue #707.
+#
class=org.apache.camel.language.simple.SimpleNoFileLanguage
diff --git a/tests/features/camel-core/src/main/java/org/apache/karaf/camel/test/CamelPollEnrichRouteSupplier.java b/tests/features/camel-core/src/main/java/org/apache/karaf/camel/test/CamelPollEnrichRouteSupplier.java
new file mode 100644
index 0000000000..e092e3f10d
--- /dev/null
+++ b/tests/features/camel-core/src/main/java/org/apache/karaf/camel/test/CamelPollEnrichRouteSupplier.java
@@ -0,0 +1,71 @@
+/*
+ * 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.karaf.camel.test;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.karaf.camel.itests.AbstractCamelSingleFeatureResultMockBasedRouteSupplier;
+import org.apache.karaf.camel.itests.CamelRouteSupplier;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Covers the resolution of the internal {@code simple-no-file} language in OSGi.
+ *
+ * When a {@code pollEnrich} is given a {@code simple} expression, {@code PollEnrichReifier} rewrites it to the
+ * {@code simple-no-file} language, so starting this route makes the Camel context resolve that name. Apache Camel
+ * ships no service file for it — {@code DefaultLanguageResolver} resolves it through a hardcoded branch — whereas
+ * camel-karaf's {@code OsgiLanguageResolver} goes through the OSGi service registry. Without the service file in
+ * the camel-core-languages bundle, this route fails to start with a {@code NoSuchLanguageException}.
+ *
+ * @see issue #707
+ */
+@Component(
+ name = "karaf-camel-poll-enrich-test",
+ immediate = true,
+ service = CamelRouteSupplier.class
+)
+public class CamelPollEnrichRouteSupplier extends AbstractCamelSingleFeatureResultMockBasedRouteSupplier {
+
+ private static final String FILE_NAME_VARIABLE = "sourceFileName";
+ private static final String SOURCE_FILE_NAME = "poll-enrich-source.txt";
+ private static final long POLL_TIMEOUT_MS = 10000L;
+
+ public String getBaseDir() {
+ return "%s/poll-enrich".formatted(System.getProperty("project.target"));
+ }
+
+ @Override
+ protected boolean consumerEnabled() {
+ // Everything happens in the producer route: it seeds the file, then polls it back.
+ return false;
+ }
+
+ @Override
+ protected void configureProducer(RouteBuilder builder, RouteDefinition producerRoute) {
+ String directory = getBaseDir();
+ producerRoute
+ .setVariable(FILE_NAME_VARIABLE, builder.constant(SOURCE_FILE_NAME))
+ .setBody(builder.constant("OK"))
+ .toF("file:%s?fileName=${variable.%s}", directory, FILE_NAME_VARIABLE)
+ // Clear the body so that only a successful enrichment can restore it.
+ .setBody(builder.constant(""))
+ .pollEnrich()
+ .simple("file:%s?fileName=${variable.%s}&initialDelay=0&delay=100"
+ .formatted(directory, FILE_NAME_VARIABLE))
+ .timeout(POLL_TIMEOUT_MS)
+ .toF("mock:%s", getResultMockName());
+ }
+}
diff --git a/tests/features/camel-core/src/test/java/org/apache/karaf/camel/itest/CamelCoreITest.java b/tests/features/camel-core/src/test/java/org/apache/karaf/camel/itest/CamelCoreITest.java
index ae16cf8abc..8c25683afc 100644
--- a/tests/features/camel-core/src/test/java/org/apache/karaf/camel/itest/CamelCoreITest.java
+++ b/tests/features/camel-core/src/test/java/org/apache/karaf/camel/itest/CamelCoreITest.java
@@ -14,6 +14,7 @@
package org.apache.karaf.camel.itest;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import org.apache.camel.component.mock.MockEndpoint;
import org.apache.karaf.camel.itests.AbstractCamelRouteWithBundleITest;
@@ -63,6 +64,11 @@ public void testCamelBean() throws Exception {
new CamelBeanITest(this).testRoutes();
}
+ @Test
+ public void testCamelPollEnrich() throws Exception {
+ new CamelPollEnrichITest(this).testRoutes();
+ }
+
public static class CamelFileITest extends AbstractCamelSingleFeatureResultFileBasedRoute {
public CamelFileITest(CamelContextProvider provider, String baseDir) {
@@ -110,4 +116,22 @@ public void configureMock(MockEndpoint mock) {
mock.expectedBodiesReceived("OK");
}
}
+
+ /**
+ * Asserts that a {@code pollEnrich} driven by a {@code simple} expression starts and enriches, which requires the
+ * internal {@code simple-no-file} language to be resolvable in OSGi. See issue #707.
+ */
+ public static class CamelPollEnrichITest extends AbstractCamelSingleFeatureResultMockBasedRoute {
+
+ public CamelPollEnrichITest(CamelContextProvider provider) {
+ super(provider);
+ }
+
+ @Override
+ public void configureMock(MockEndpoint mock) {
+ // The route seeds a file and polls it back, so allow more headroom than the 10s default.
+ mock.setResultWaitTime(TimeUnit.SECONDS.toMillis(30));
+ mock.expectedBodiesReceived("OK");
+ }
+ }
}
\ No newline at end of file